blob: dba3591cbdb4596c35fab4a3f1cef969b4907cef [file] [log] [blame]
Jungshik Jang187d0172014-06-17 17:48:42 +09001/*
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
Jungshik Jangea67c182014-06-19 22:19:20 +090019import android.annotation.Nullable;
Jinsuk Kimc0c20d02014-07-04 14:34:31 +090020import android.hardware.hdmi.HdmiControlManager;
Jungshik Jangea67c182014-06-19 22:19:20 +090021import android.hardware.hdmi.IHdmiControlCallback;
22import android.os.RemoteException;
Jungshik Jang187d0172014-06-17 17:48:42 +090023import android.util.Slog;
24
25import com.android.server.hdmi.HdmiControlService.SendMessageCallback;
26
27/**
28 * Action to update audio status (volume or mute) of audio amplifier
29 */
Jungshik Jangb509c2e2014-08-07 13:45:01 +090030final class SystemAudioStatusAction extends HdmiCecFeatureAction {
Jungshik Jang187d0172014-06-17 17:48:42 +090031 private static final String TAG = "SystemAudioStatusAction";
32
33 // State that waits for <ReportAudioStatus>.
34 private static final int STATE_WAIT_FOR_REPORT_AUDIO_STATUS = 1;
35
36 private final int mAvrAddress;
Jungshik Jangea67c182014-06-19 22:19:20 +090037 @Nullable private final IHdmiControlCallback mCallback;
Jungshik Jang187d0172014-06-17 17:48:42 +090038
Jungshik Jangea67c182014-06-19 22:19:20 +090039 SystemAudioStatusAction(HdmiCecLocalDevice source, int avrAddress,
40 IHdmiControlCallback callback) {
Jungshik Jang187d0172014-06-17 17:48:42 +090041 super(source);
42 mAvrAddress = avrAddress;
Jungshik Jangea67c182014-06-19 22:19:20 +090043 mCallback = callback;
Jungshik Jang187d0172014-06-17 17:48:42 +090044 }
45
46 @Override
47 boolean start() {
48 mState = STATE_WAIT_FOR_REPORT_AUDIO_STATUS;
Jinsuk Kim5fba96d2014-07-11 11:51:34 +090049 addTimer(mState, HdmiConfig.TIMEOUT_MS);
Jungshik Jang187d0172014-06-17 17:48:42 +090050 sendGiveAudioStatus();
51 return true;
52 }
53
54 private void sendGiveAudioStatus() {
55 sendCommand(HdmiCecMessageBuilder.buildGiveAudioStatus(getSourceAddress(), mAvrAddress),
56 new SendMessageCallback() {
57 @Override
58 public void onSendCompleted(int error) {
Jinsuk Kimc0c20d02014-07-04 14:34:31 +090059 if (error != Constants.SEND_RESULT_SUCCESS) {
Jungshik Jang187d0172014-06-17 17:48:42 +090060 handleSendGiveAudioStatusFailure();
61 }
62 }
63 });
64 }
65
66 private void handleSendGiveAudioStatusFailure() {
67 // Inform to all application that the audio status (volumn, mute) of
68 // the audio amplifier is unknown.
Jinsuk Kimc0c20d02014-07-04 14:34:31 +090069 tv().setAudioStatus(false, Constants.UNKNOWN_VOLUME);
Jungshik Jang187d0172014-06-17 17:48:42 +090070
Jungshik Jang377dcbd2014-07-15 15:49:02 +090071 int uiCommand = tv().isSystemAudioActivated()
Jungshik Jang210d73d2014-07-04 11:11:29 +090072 ? HdmiCecKeycode.CEC_KEYCODE_RESTORE_VOLUME_FUNCTION // SystemAudioMode: ON
73 : HdmiCecKeycode.CEC_KEYCODE_MUTE_FUNCTION; // SystemAudioMode: OFF
Jungshik Jang8fa36b12014-06-25 15:51:36 +090074 sendUserControlPressedAndReleased(mAvrAddress, uiCommand);
Jungshik Jangea67c182014-06-19 22:19:20 +090075
76 // Still return SUCCESS to callback.
Jinsuk Kimc0c20d02014-07-04 14:34:31 +090077 finishWithCallback(HdmiControlManager.RESULT_SUCCESS);
Jungshik Jang187d0172014-06-17 17:48:42 +090078 }
79
Jungshik Jang187d0172014-06-17 17:48:42 +090080 @Override
81 boolean processCommand(HdmiCecMessage cmd) {
Jungshik Jang5352081c2014-09-22 15:14:49 +090082 if (mState != STATE_WAIT_FOR_REPORT_AUDIO_STATUS || mAvrAddress != cmd.getSource()) {
Jungshik Jang187d0172014-06-17 17:48:42 +090083 return false;
84 }
85
86 switch (cmd.getOpcode()) {
Jinsuk Kimc0c20d02014-07-04 14:34:31 +090087 case Constants.MESSAGE_REPORT_AUDIO_STATUS:
Jungshik Jang187d0172014-06-17 17:48:42 +090088 handleReportAudioStatus(cmd);
89 return true;
90 }
91
92 return false;
93 }
94
95 private void handleReportAudioStatus(HdmiCecMessage cmd) {
96 byte[] params = cmd.getParams();
Yuncheol Heo75a77e72014-07-09 18:27:53 +090097 boolean mute = (params[0] & 0x80) == 0x80;
98 int volume = params[0] & 0x7F;
99 tv().setAudioStatus(mute, volume);
Jungshik Jang187d0172014-06-17 17:48:42 +0900100
Jungshik Jang377dcbd2014-07-15 15:49:02 +0900101 if (!(tv().isSystemAudioActivated() ^ mute)) {
Yuncheol Heo75a77e72014-07-09 18:27:53 +0900102 // Toggle AVR's mute status to match with the system audio status.
103 sendUserControlPressedAndReleased(mAvrAddress, HdmiCecKeycode.CEC_KEYCODE_MUTE);
Jungshik Jang187d0172014-06-17 17:48:42 +0900104 }
Yuncheol Heo75a77e72014-07-09 18:27:53 +0900105 finishWithCallback(HdmiControlManager.RESULT_SUCCESS);
Jungshik Jang187d0172014-06-17 17:48:42 +0900106 }
107
Jungshik Jangea67c182014-06-19 22:19:20 +0900108 private void finishWithCallback(int returnCode) {
109 if (mCallback != null) {
110 try {
111 mCallback.onComplete(returnCode);
112 } catch (RemoteException e) {
113 Slog.e(TAG, "Failed to invoke callback.", e);
114 }
115 }
116 finish();
117 }
118
Jungshik Jang187d0172014-06-17 17:48:42 +0900119 @Override
120 void handleTimerEvent(int state) {
121 if (mState != state) {
122 return;
123 }
124
125 handleSendGiveAudioStatusFailure();
126 }
127}