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.tv.cec.V1_0.SendMessageResult; 20import com.android.server.hdmi.HdmiControlService.SendMessageCallback; 21 22/** 23 * Action to initiate system audio once AVR is detected on Device discovery action. 24 */ 25// Seq #27 26final class SystemAudioAutoInitiationAction extends HdmiCecFeatureAction { 27 private final int mAvrAddress; 28 29 // State that waits for <System Audio Mode Status> once send 30 // <Give System Audio Mode Status> to AV Receiver. 31 private static final int STATE_WAITING_FOR_SYSTEM_AUDIO_MODE_STATUS = 1; 32 33 SystemAudioAutoInitiationAction(HdmiCecLocalDevice source, int avrAddress) { 34 super(source); 35 mAvrAddress = avrAddress; 36 } 37 38 @Override 39 boolean start() { 40 mState = STATE_WAITING_FOR_SYSTEM_AUDIO_MODE_STATUS; 41 42 addTimer(mState, HdmiConfig.TIMEOUT_MS); 43 sendGiveSystemAudioModeStatus(); 44 return true; 45 } 46 47 private void sendGiveSystemAudioModeStatus() { 48 sendCommand(HdmiCecMessageBuilder.buildGiveSystemAudioModeStatus(getSourceAddress(), 49 mAvrAddress), new SendMessageCallback() { 50 @Override 51 public void onSendCompleted(int error) { 52 if (error != SendMessageResult.SUCCESS) { 53 tv().setSystemAudioMode(false); 54 finish(); 55 } 56 } 57 }); 58 } 59 60 @Override 61 boolean processCommand(HdmiCecMessage cmd) { 62 if (mState != STATE_WAITING_FOR_SYSTEM_AUDIO_MODE_STATUS 63 || mAvrAddress != cmd.getSource()) { 64 return false; 65 } 66 67 if (cmd.getOpcode() == Constants.MESSAGE_SYSTEM_AUDIO_MODE_STATUS) { 68 handleSystemAudioModeStatusMessage(HdmiUtils.parseCommandParamSystemAudioStatus(cmd)); 69 return true; 70 } 71 return false; 72 } 73 74 private void handleSystemAudioModeStatusMessage(boolean currentSystemAudioMode) { 75 if (!canChangeSystemAudio()) { 76 HdmiLogger.debug("Cannot change system audio mode in auto initiation action."); 77 finish(); 78 return; 79 } 80 81 // If System Audio Control feature is enabled, turn on system audio mode when new AVR is 82 // detected. Otherwise, turn off system audio mode. 83 boolean targetSystemAudioMode = tv().isSystemAudioControlFeatureEnabled(); 84 if (currentSystemAudioMode != targetSystemAudioMode) { 85 // Start System Audio Control feature actions only if necessary. 86 addAndStartAction( 87 new SystemAudioActionFromTv(tv(), mAvrAddress, targetSystemAudioMode, null)); 88 } else { 89 // If AVR already has correct system audio mode, update target system audio mode 90 // immediately rather than starting feature action. 91 tv().setSystemAudioMode(targetSystemAudioMode); 92 } 93 finish(); 94 } 95 96 @Override 97 void handleTimerEvent(int state) { 98 if (mState != state) { 99 return; 100 } 101 102 switch (mState) { 103 case STATE_WAITING_FOR_SYSTEM_AUDIO_MODE_STATUS: 104 handleSystemAudioModeStatusTimeout(); 105 break; 106 } 107 } 108 109 private void handleSystemAudioModeStatusTimeout() { 110 if (!canChangeSystemAudio()) { 111 HdmiLogger.debug("Cannot change system audio mode in auto initiation action."); 112 finish(); 113 return; 114 } 115 // If we can't get the current system audio mode status, just try to turn on/off system 116 // audio mode according to the system audio control setting. 117 addAndStartAction(new SystemAudioActionFromTv(tv(), mAvrAddress, 118 tv().isSystemAudioControlFeatureEnabled(), null)); 119 finish(); 120 } 121 122 private boolean canChangeSystemAudio() { 123 return !(tv().hasAction(SystemAudioActionFromTv.class) 124 || tv().hasAction(SystemAudioActionFromAvr.class)); 125 } 126} 127