SystemAudioStatusAction.java revision 187d01765b935d07936f74343b4f4af590c239a1
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 23import com.android.server.hdmi.HdmiControlService.SendMessageCallback; 24 25/** 26 * Action to update audio status (volume or mute) of audio amplifier 27 */ 28// TODO: refactor SystemAudioMode so that it uses this class instead of internal state. 29final class SystemAudioStatusAction extends FeatureAction { 30 private static final String TAG = "SystemAudioStatusAction"; 31 32 // State that waits for <ReportAudioStatus>. 33 private static final int STATE_WAIT_FOR_REPORT_AUDIO_STATUS = 1; 34 35 private final int mAvrAddress; 36 37 SystemAudioStatusAction(HdmiCecLocalDevice source, int avrAddress) { 38 super(source); 39 mAvrAddress = avrAddress; 40 } 41 42 @Override 43 boolean start() { 44 mState = STATE_WAIT_FOR_REPORT_AUDIO_STATUS; 45 addTimer(mState, TIMEOUT_MS); 46 sendGiveAudioStatus(); 47 return true; 48 } 49 50 private void sendGiveAudioStatus() { 51 sendCommand(HdmiCecMessageBuilder.buildGiveAudioStatus(getSourceAddress(), mAvrAddress), 52 new SendMessageCallback() { 53 @Override 54 public void onSendCompleted(int error) { 55 if (error != HdmiConstants.SEND_RESULT_SUCCESS) { 56 handleSendGiveAudioStatusFailure(); 57 } 58 } 59 }); 60 } 61 62 private void handleSendGiveAudioStatusFailure() { 63 // Inform to all application that the audio status (volumn, mute) of 64 // the audio amplifier is unknown. 65 tv().setAudioStatus(false, HdmiConstants.UNKNOWN_VOLUME); 66 67 int uiCommand = tv().getSystemAudioMode() 68 ? HdmiConstants.UI_COMMAND_RESTORE_VOLUME_FUNCTION // SystemAudioMode: ON 69 : HdmiConstants.UI_COMMAND_MUTE_FUNCTION; // SystemAudioMode: OFF 70 sendUserControlPressedAndReleased(uiCommand); 71 finish(); 72 } 73 74 private void sendUserControlPressedAndReleased(int uiCommand) { 75 sendCommand(HdmiCecMessageBuilder.buildUserControlPressed( 76 getSourceAddress(), mAvrAddress, uiCommand)); 77 sendCommand(HdmiCecMessageBuilder.buildUserControlReleased( 78 getSourceAddress(), mAvrAddress)); 79 } 80 81 @Override 82 boolean processCommand(HdmiCecMessage cmd) { 83 if (mState != STATE_WAIT_FOR_REPORT_AUDIO_STATUS) { 84 return false; 85 } 86 87 switch (cmd.getOpcode()) { 88 case HdmiCec.MESSAGE_REPORT_AUDIO_STATUS: 89 handleReportAudioStatus(cmd); 90 return true; 91 } 92 93 return false; 94 } 95 96 private void handleReportAudioStatus(HdmiCecMessage cmd) { 97 byte[] params = cmd.getParams(); 98 if (params.length > 0) { 99 boolean mute = (params[0] & 0x80) == 0x80; 100 int volume = params[0] & 0x7F; 101 tv().setAudioStatus(mute, volume); 102 103 if ((tv().getSystemAudioMode() && mute) || (!tv().getSystemAudioMode() && !mute)) { 104 // Toggle AVR's mute status to match with the system audio status. 105 sendUserControlPressedAndReleased(HdmiConstants.UI_COMMAND_MUTE); 106 } 107 finish(); 108 } else { 109 Slog.e(TAG, "Invalid <Report Audio Status> message:" + cmd); 110 handleSendGiveAudioStatusFailure(); 111 return; 112 } 113 } 114 115 @Override 116 void handleTimerEvent(int state) { 117 if (mState != state) { 118 return; 119 } 120 121 handleSendGiveAudioStatusFailure(); 122 } 123} 124