SystemAudioAction.java revision 16321b80077815eebeceee249ff7a29e336e04a4
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; 21 22/** 23 * Base feature action class for SystemAudioActionFromTv and SystemAudioActionFromAvr. 24 */ 25abstract class SystemAudioAction extends FeatureAction { 26 private static final String TAG = "SystemAudioAction"; 27 28 // State in which waits for <SetSystemAudioMode>. 29 private static final int STATE_WAIT_FOR_SET_SYSTEM_AUDIO_MODE = 1; 30 31 private static final int MAX_SEND_RETRY_COUNT = 2; 32 33 private static final int ON_TIMEOUT_MS = 5000; 34 private static final int OFF_TIMEOUT_MS = TIMEOUT_MS; 35 36 // Logical address of AV Receiver. 37 protected final int mAvrLogicalAddress; 38 39 // The target audio status of the action, whether to enable the system audio mode or not. 40 protected boolean mTargetAudioStatus; 41 42 private int mSendRetryCount = 0; 43 44 /** 45 * Constructor 46 * 47 * @param source {@link HdmiCecLocalDevice} instance 48 * @param avrAddress logical address of AVR device 49 * @param targetStatus Whether to enable the system audio mode or not 50 * @throw IllegalArugmentException if device type of sourceAddress and avrAddress is invalid 51 */ 52 SystemAudioAction(HdmiCecLocalDevice source, int avrAddress, boolean targetStatus) { 53 super(source); 54 HdmiUtils.verifyAddressType(avrAddress, HdmiCec.DEVICE_AUDIO_SYSTEM); 55 mAvrLogicalAddress = avrAddress; 56 mTargetAudioStatus = targetStatus; 57 } 58 59 protected void sendSystemAudioModeRequest() { 60 int avrPhysicalAddress = tv().getAvrDeviceInfo().getPhysicalAddress(); 61 HdmiCecMessage command = HdmiCecMessageBuilder.buildSystemAudioModeRequest( 62 getSourceAddress(), 63 mAvrLogicalAddress, avrPhysicalAddress, mTargetAudioStatus); 64 sendCommand(command, new HdmiControlService.SendMessageCallback() { 65 @Override 66 public void onSendCompleted(int error) { 67 if (error == HdmiConstants.SEND_RESULT_SUCCESS) { 68 mState = STATE_WAIT_FOR_SET_SYSTEM_AUDIO_MODE; 69 addTimer(mState, mTargetAudioStatus ? ON_TIMEOUT_MS : OFF_TIMEOUT_MS); 70 } else { 71 setSystemAudioMode(false); 72 finish(); 73 } 74 } 75 }); 76 } 77 78 private void handleSendSystemAudioModeRequestTimeout() { 79 if (!mTargetAudioStatus // Don't retry for Off case. 80 || mSendRetryCount++ >= MAX_SEND_RETRY_COUNT) { 81 setSystemAudioMode(false); 82 finish(); 83 return; 84 } 85 sendSystemAudioModeRequest(); 86 } 87 88 protected void setSystemAudioMode(boolean mode) { 89 tv().setSystemAudioMode(mode); 90 } 91 92 @Override 93 final boolean processCommand(HdmiCecMessage cmd) { 94 switch (mState) { 95 case STATE_WAIT_FOR_SET_SYSTEM_AUDIO_MODE: 96 // TODO: Handle <FeatureAbort> of <SystemAudioModeRequest> 97 if (cmd.getOpcode() != HdmiCec.MESSAGE_SET_SYSTEM_AUDIO_MODE 98 || !HdmiUtils.checkCommandSource(cmd, mAvrLogicalAddress, TAG)) { 99 return false; 100 } 101 boolean receivedStatus = HdmiUtils.parseCommandParamSystemAudioStatus(cmd); 102 if (receivedStatus == mTargetAudioStatus) { 103 setSystemAudioMode(receivedStatus); 104 startAudioStatusAction(); 105 return true; 106 } else { 107 // Unexpected response, consider the request is newly initiated by AVR. 108 // To return 'false' will initiate new SystemAudioActionFromAvr by the control 109 // service. 110 finish(); 111 return false; 112 } 113 default: 114 return false; 115 } 116 } 117 118 protected void startAudioStatusAction() { 119 addAndStartAction(new SystemAudioStatusAction(tv(), mAvrLogicalAddress)); 120 finish(); 121 } 122 123 protected void removeSystemAudioActionInProgress() { 124 removeActionExcept(SystemAudioActionFromTv.class, this); 125 removeActionExcept(SystemAudioActionFromAvr.class, this); 126 } 127 128 @Override 129 final void handleTimerEvent(int state) { 130 if (mState != state) { 131 return; 132 } 133 switch (mState) { 134 case STATE_WAIT_FOR_SET_SYSTEM_AUDIO_MODE: 135 handleSendSystemAudioModeRequestTimeout(); 136 return; 137 } 138 } 139} 140