SystemAudioAutoInitiationAction.java revision c0c20d0522d7756d80f011e7a54bf3b51c78df41
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 com.android.server.hdmi.HdmiControlService.SendMessageCallback;
20
21/**
22 * Action to initiate system audio once AVR is detected on Device discovery action.
23 */
24final class SystemAudioAutoInitiationAction extends FeatureAction {
25    private final int mAvrAddress;
26
27    // State that waits for <System Audio Mode Status> once send
28    // <Give System Audio Mode Status> to AV Receiver.
29    private static final int STATE_WAITING_FOR_SYSTEM_AUDIO_MODE_STATUS = 1;
30
31    SystemAudioAutoInitiationAction(HdmiCecLocalDevice source, int avrAddress) {
32        super(source);
33        mAvrAddress = avrAddress;
34    }
35
36    @Override
37    boolean start() {
38        mState = STATE_WAITING_FOR_SYSTEM_AUDIO_MODE_STATUS;
39
40        addTimer(mState, TIMEOUT_MS);
41        sendGiveSystemAudioModeStatus();
42        return true;
43    }
44
45    private void sendGiveSystemAudioModeStatus() {
46        sendCommand(HdmiCecMessageBuilder.buildGiveSystemAudioModeStatus(getSourceAddress(),
47                mAvrAddress), new SendMessageCallback() {
48            @Override
49            public void onSendCompleted(int error) {
50                if (error != Constants.SEND_RESULT_SUCCESS) {
51                    tv().setSystemAudioMode(false);
52                    finish();
53                }
54            }
55        });
56    }
57
58    @Override
59    boolean processCommand(HdmiCecMessage cmd) {
60        if (mState != STATE_WAITING_FOR_SYSTEM_AUDIO_MODE_STATUS) {
61            return false;
62        }
63
64        switch (cmd.getOpcode()) {
65            case Constants.MESSAGE_SYSTEM_AUDIO_MODE_STATUS:
66                handleSystemAudioModeStatusMessage();
67                return true;
68            default:
69                return false;
70        }
71    }
72
73    private void handleSystemAudioModeStatusMessage() {
74        // If the last setting is system audio, turn on system audio whatever AVR status is.
75        if (tv().getSystemAudioMode()) {
76            if (canChangeSystemAudio()) {
77                addAndStartAction(new SystemAudioActionFromTv(tv(), mAvrAddress, true, null));
78            }
79        } else {
80            // If the last setting is non-system audio, turn off system audio mode
81            // and update system audio status (volume or mute).
82            tv().setSystemAudioMode(false);
83            if (canChangeSystemAudio()) {
84                addAndStartAction(new SystemAudioStatusAction(tv(), mAvrAddress, null));
85            }
86        }
87        finish();
88    }
89
90    @Override
91    void handleTimerEvent(int state) {
92        if (mState != state) {
93            return;
94        }
95
96        switch (mState) {
97            case STATE_WAITING_FOR_SYSTEM_AUDIO_MODE_STATUS:
98                handleSystemAudioModeStatusTimeout();
99                break;
100        }
101    }
102
103    private void handleSystemAudioModeStatusTimeout() {
104        if (tv().getSystemAudioMode()) {
105            if (canChangeSystemAudio()) {
106                addAndStartAction(new SystemAudioActionFromTv(tv(), mAvrAddress, true, null));
107            }
108        } else {
109            tv().setSystemAudioMode(false);
110        }
111        finish();
112    }
113
114    private boolean canChangeSystemAudio() {
115        return !(tv().hasAction(SystemAudioActionFromTv.class)
116               || tv().hasAction(SystemAudioActionFromAvr.class));
117    }
118}
119