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