1187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang/* 2187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang * Copyright (C) 2014 The Android Open Source Project 3187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang * 4187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang * Licensed under the Apache License, Version 2.0 (the "License"); 5187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang * you may not use this file except in compliance with the License. 6187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang * You may obtain a copy of the License at 7187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang * 8187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang * http://www.apache.org/licenses/LICENSE-2.0 9187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang * 10187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang * Unless required by applicable law or agreed to in writing, software 11187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang * distributed under the License is distributed on an "AS IS" BASIS, 12187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang * See the License for the specific language governing permissions and 14187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang * limitations under the License. 15187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang */ 16187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang 17187d01765b935d07936f74343b4f4af590c239a1Jungshik Jangpackage com.android.server.hdmi; 18187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang 19bc6e372b25d7d62efecefba09304c5a66218c91aDonghyun Choimport android.hardware.tv.cec.V1_0.SendMessageResult; 20187d01765b935d07936f74343b4f4af590c239a1Jungshik Jangimport com.android.server.hdmi.HdmiControlService.SendMessageCallback; 21187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang 22187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang/** 23187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang * Action to initiate system audio once AVR is detected on Device discovery action. 24187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang */ 25c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo// Seq #27 26b509c2ecd99619248b7a07fb0fa978bb27f25cc3Jungshik Jangfinal class SystemAudioAutoInitiationAction extends HdmiCecFeatureAction { 27187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang private final int mAvrAddress; 28187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang 29187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang // State that waits for <System Audio Mode Status> once send 30187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang // <Give System Audio Mode Status> to AV Receiver. 31187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang private static final int STATE_WAITING_FOR_SYSTEM_AUDIO_MODE_STATUS = 1; 32187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang 33187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang SystemAudioAutoInitiationAction(HdmiCecLocalDevice source, int avrAddress) { 34187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang super(source); 35187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang mAvrAddress = avrAddress; 36187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang } 37187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang 38187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang @Override 39187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang boolean start() { 40187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang mState = STATE_WAITING_FOR_SYSTEM_AUDIO_MODE_STATUS; 41187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang 425fba96df30b6b50b3cb9fe1d783320b1cc3bd6eaJinsuk Kim addTimer(mState, HdmiConfig.TIMEOUT_MS); 43187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang sendGiveSystemAudioModeStatus(); 44187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang return true; 45187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang } 46187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang 47187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang private void sendGiveSystemAudioModeStatus() { 48187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang sendCommand(HdmiCecMessageBuilder.buildGiveSystemAudioModeStatus(getSourceAddress(), 49187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang mAvrAddress), new SendMessageCallback() { 50187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang @Override 51187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang public void onSendCompleted(int error) { 52bc6e372b25d7d62efecefba09304c5a66218c91aDonghyun Cho if (error != SendMessageResult.SUCCESS) { 53c1fa9afbcd1cafd205d46b2fd0bdaadccb7d29eaDonghyun Cho tv().setSystemAudioMode(false); 54187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang finish(); 55187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang } 56187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang } 57187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang }); 58187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang } 59187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang 60187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang @Override 61187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang boolean processCommand(HdmiCecMessage cmd) { 625352081c662299b618335bf3024058fa04ef2dfdJungshik Jang if (mState != STATE_WAITING_FOR_SYSTEM_AUDIO_MODE_STATUS 635352081c662299b618335bf3024058fa04ef2dfdJungshik Jang || mAvrAddress != cmd.getSource()) { 64187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang return false; 65187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang } 66187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang 675352081c662299b618335bf3024058fa04ef2dfdJungshik Jang if (cmd.getOpcode() == Constants.MESSAGE_SYSTEM_AUDIO_MODE_STATUS) { 68c21f63aa9514fb5f34e195fade88f8545d935992Donghyun Cho handleSystemAudioModeStatusMessage(HdmiUtils.parseCommandParamSystemAudioStatus(cmd)); 695352081c662299b618335bf3024058fa04ef2dfdJungshik Jang return true; 70187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang } 715352081c662299b618335bf3024058fa04ef2dfdJungshik Jang return false; 72187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang } 73187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang 74c1fa9afbcd1cafd205d46b2fd0bdaadccb7d29eaDonghyun Cho private void handleSystemAudioModeStatusMessage(boolean currentSystemAudioMode) { 757fb8e7f4ff524f9131a387efc2649aa78e4ae376Jungshik Jang if (!canChangeSystemAudio()) { 767fb8e7f4ff524f9131a387efc2649aa78e4ae376Jungshik Jang HdmiLogger.debug("Cannot change system audio mode in auto initiation action."); 777fb8e7f4ff524f9131a387efc2649aa78e4ae376Jungshik Jang finish(); 787fb8e7f4ff524f9131a387efc2649aa78e4ae376Jungshik Jang return; 79187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang } 807fb8e7f4ff524f9131a387efc2649aa78e4ae376Jungshik Jang 81c1fa9afbcd1cafd205d46b2fd0bdaadccb7d29eaDonghyun Cho // If System Audio Control feature is enabled, turn on system audio mode when new AVR is 82c1fa9afbcd1cafd205d46b2fd0bdaadccb7d29eaDonghyun Cho // detected. Otherwise, turn off system audio mode. 83c1fa9afbcd1cafd205d46b2fd0bdaadccb7d29eaDonghyun Cho boolean targetSystemAudioMode = tv().isSystemAudioControlFeatureEnabled(); 84c1fa9afbcd1cafd205d46b2fd0bdaadccb7d29eaDonghyun Cho if (currentSystemAudioMode != targetSystemAudioMode) { 85c1fa9afbcd1cafd205d46b2fd0bdaadccb7d29eaDonghyun Cho // Start System Audio Control feature actions only if necessary. 86c1fa9afbcd1cafd205d46b2fd0bdaadccb7d29eaDonghyun Cho addAndStartAction( 87c1fa9afbcd1cafd205d46b2fd0bdaadccb7d29eaDonghyun Cho new SystemAudioActionFromTv(tv(), mAvrAddress, targetSystemAudioMode, null)); 88c21f63aa9514fb5f34e195fade88f8545d935992Donghyun Cho } else { 89c1fa9afbcd1cafd205d46b2fd0bdaadccb7d29eaDonghyun Cho // If AVR already has correct system audio mode, update target system audio mode 90c1fa9afbcd1cafd205d46b2fd0bdaadccb7d29eaDonghyun Cho // immediately rather than starting feature action. 91c1fa9afbcd1cafd205d46b2fd0bdaadccb7d29eaDonghyun Cho tv().setSystemAudioMode(targetSystemAudioMode); 92c21f63aa9514fb5f34e195fade88f8545d935992Donghyun Cho } 93187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang finish(); 94187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang } 95187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang 96187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang @Override 97187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang void handleTimerEvent(int state) { 98187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang if (mState != state) { 99187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang return; 100187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang } 101187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang 102187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang switch (mState) { 103187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang case STATE_WAITING_FOR_SYSTEM_AUDIO_MODE_STATUS: 104187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang handleSystemAudioModeStatusTimeout(); 105187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang break; 106187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang } 107187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang } 108187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang 109187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang private void handleSystemAudioModeStatusTimeout() { 110c1fa9afbcd1cafd205d46b2fd0bdaadccb7d29eaDonghyun Cho if (!canChangeSystemAudio()) { 111c1fa9afbcd1cafd205d46b2fd0bdaadccb7d29eaDonghyun Cho HdmiLogger.debug("Cannot change system audio mode in auto initiation action."); 112c1fa9afbcd1cafd205d46b2fd0bdaadccb7d29eaDonghyun Cho finish(); 113c1fa9afbcd1cafd205d46b2fd0bdaadccb7d29eaDonghyun Cho return; 114187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang } 115c1fa9afbcd1cafd205d46b2fd0bdaadccb7d29eaDonghyun Cho // If we can't get the current system audio mode status, just try to turn on/off system 116c1fa9afbcd1cafd205d46b2fd0bdaadccb7d29eaDonghyun Cho // audio mode according to the system audio control setting. 117c1fa9afbcd1cafd205d46b2fd0bdaadccb7d29eaDonghyun Cho addAndStartAction(new SystemAudioActionFromTv(tv(), mAvrAddress, 118c1fa9afbcd1cafd205d46b2fd0bdaadccb7d29eaDonghyun Cho tv().isSystemAudioControlFeatureEnabled(), null)); 119187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang finish(); 120187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang } 121187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang 122187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang private boolean canChangeSystemAudio() { 123a858d221ff86c497e745222ea15bab141e337636Jungshik Jang return !(tv().hasAction(SystemAudioActionFromTv.class) 124a858d221ff86c497e745222ea15bab141e337636Jungshik Jang || tv().hasAction(SystemAudioActionFromAvr.class)); 125187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang } 126187d01765b935d07936f74343b4f4af590c239a1Jungshik Jang} 127