SystemAudioStatusAction.java revision 210d73df0b77b4c8be67ecc92afb238dc8c7ccfa
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.annotation.Nullable; 20import android.hardware.hdmi.HdmiCec; 21import android.hardware.hdmi.HdmiCecMessage; 22import android.hardware.hdmi.IHdmiControlCallback; 23import android.os.RemoteException; 24import android.util.Slog; 25 26import com.android.server.hdmi.HdmiControlService.SendMessageCallback; 27 28/** 29 * Action to update audio status (volume or mute) of audio amplifier 30 */ 31final class SystemAudioStatusAction extends FeatureAction { 32 private static final String TAG = "SystemAudioStatusAction"; 33 34 // State that waits for <ReportAudioStatus>. 35 private static final int STATE_WAIT_FOR_REPORT_AUDIO_STATUS = 1; 36 37 private final int mAvrAddress; 38 @Nullable private final IHdmiControlCallback mCallback; 39 40 SystemAudioStatusAction(HdmiCecLocalDevice source, int avrAddress, 41 IHdmiControlCallback callback) { 42 super(source); 43 mAvrAddress = avrAddress; 44 mCallback = callback; 45 } 46 47 @Override 48 boolean start() { 49 mState = STATE_WAIT_FOR_REPORT_AUDIO_STATUS; 50 addTimer(mState, TIMEOUT_MS); 51 sendGiveAudioStatus(); 52 return true; 53 } 54 55 private void sendGiveAudioStatus() { 56 sendCommand(HdmiCecMessageBuilder.buildGiveAudioStatus(getSourceAddress(), mAvrAddress), 57 new SendMessageCallback() { 58 @Override 59 public void onSendCompleted(int error) { 60 if (error != HdmiConstants.SEND_RESULT_SUCCESS) { 61 handleSendGiveAudioStatusFailure(); 62 } 63 } 64 }); 65 } 66 67 private void handleSendGiveAudioStatusFailure() { 68 // Inform to all application that the audio status (volumn, mute) of 69 // the audio amplifier is unknown. 70 tv().setAudioStatus(false, HdmiConstants.UNKNOWN_VOLUME); 71 72 int uiCommand = tv().getSystemAudioMode() 73 ? HdmiCecKeycode.CEC_KEYCODE_RESTORE_VOLUME_FUNCTION // SystemAudioMode: ON 74 : HdmiCecKeycode.CEC_KEYCODE_MUTE_FUNCTION; // SystemAudioMode: OFF 75 sendUserControlPressedAndReleased(mAvrAddress, uiCommand); 76 77 // Still return SUCCESS to callback. 78 finishWithCallback(HdmiCec.RESULT_SUCCESS); 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(mAvrAddress, HdmiCecKeycode.CEC_KEYCODE_MUTE); 106 } 107 finishWithCallback(HdmiCec.RESULT_SUCCESS); 108 } else { 109 Slog.e(TAG, "Invalid <Report Audio Status> message:" + cmd); 110 handleSendGiveAudioStatusFailure(); 111 return; 112 } 113 } 114 115 private void finishWithCallback(int returnCode) { 116 if (mCallback != null) { 117 try { 118 mCallback.onComplete(returnCode); 119 } catch (RemoteException e) { 120 Slog.e(TAG, "Failed to invoke callback.", e); 121 } 122 } 123 finish(); 124 } 125 126 @Override 127 void handleTimerEvent(int state) { 128 if (mState != state) { 129 return; 130 } 131 132 handleSendGiveAudioStatusFailure(); 133 } 134} 135