Home | History | Annotate | Download | only in hdmi
      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 
     17 package com.android.server.hdmi;
     18 
     19 import android.hardware.tv.cec.V1_0.SendMessageResult;
     20 import com.android.server.hdmi.HdmiControlService.SendMessageCallback;
     21 
     22 /**
     23  * Action to initiate system audio once AVR is detected on Device discovery action.
     24  */
     25 // Seq #27
     26 final class SystemAudioAutoInitiationAction extends HdmiCecFeatureAction {
     27     private final int mAvrAddress;
     28 
     29     // State that waits for <System Audio Mode Status> once send
     30     // <Give System Audio Mode Status> to AV Receiver.
     31     private static final int STATE_WAITING_FOR_SYSTEM_AUDIO_MODE_STATUS = 1;
     32 
     33     SystemAudioAutoInitiationAction(HdmiCecLocalDevice source, int avrAddress) {
     34         super(source);
     35         mAvrAddress = avrAddress;
     36     }
     37 
     38     @Override
     39     boolean start() {
     40         mState = STATE_WAITING_FOR_SYSTEM_AUDIO_MODE_STATUS;
     41 
     42         addTimer(mState, HdmiConfig.TIMEOUT_MS);
     43         sendGiveSystemAudioModeStatus();
     44         return true;
     45     }
     46 
     47     private void sendGiveSystemAudioModeStatus() {
     48         sendCommand(HdmiCecMessageBuilder.buildGiveSystemAudioModeStatus(getSourceAddress(),
     49                 mAvrAddress), new SendMessageCallback() {
     50             @Override
     51             public void onSendCompleted(int error) {
     52                 if (error != SendMessageResult.SUCCESS) {
     53                     tv().setSystemAudioMode(false);
     54                     finish();
     55                 }
     56             }
     57         });
     58     }
     59 
     60     @Override
     61     boolean processCommand(HdmiCecMessage cmd) {
     62         if (mState != STATE_WAITING_FOR_SYSTEM_AUDIO_MODE_STATUS
     63                 || mAvrAddress != cmd.getSource()) {
     64             return false;
     65         }
     66 
     67         if (cmd.getOpcode() == Constants.MESSAGE_SYSTEM_AUDIO_MODE_STATUS) {
     68             handleSystemAudioModeStatusMessage(HdmiUtils.parseCommandParamSystemAudioStatus(cmd));
     69             return true;
     70         }
     71         return false;
     72     }
     73 
     74     private void handleSystemAudioModeStatusMessage(boolean currentSystemAudioMode) {
     75         if (!canChangeSystemAudio()) {
     76             HdmiLogger.debug("Cannot change system audio mode in auto initiation action.");
     77             finish();
     78             return;
     79         }
     80 
     81         // If System Audio Control feature is enabled, turn on system audio mode when new AVR is
     82         // detected. Otherwise, turn off system audio mode.
     83         boolean targetSystemAudioMode = tv().isSystemAudioControlFeatureEnabled();
     84         if (currentSystemAudioMode != targetSystemAudioMode) {
     85             // Start System Audio Control feature actions only if necessary.
     86             addAndStartAction(
     87                     new SystemAudioActionFromTv(tv(), mAvrAddress, targetSystemAudioMode, null));
     88         } else {
     89             // If AVR already has correct system audio mode, update target system audio mode
     90             // immediately rather than starting feature action.
     91             tv().setSystemAudioMode(targetSystemAudioMode);
     92         }
     93         finish();
     94     }
     95 
     96     @Override
     97     void handleTimerEvent(int state) {
     98         if (mState != state) {
     99             return;
    100         }
    101 
    102         switch (mState) {
    103             case STATE_WAITING_FOR_SYSTEM_AUDIO_MODE_STATUS:
    104                 handleSystemAudioModeStatusTimeout();
    105                 break;
    106         }
    107     }
    108 
    109     private void handleSystemAudioModeStatusTimeout() {
    110         if (!canChangeSystemAudio()) {
    111             HdmiLogger.debug("Cannot change system audio mode in auto initiation action.");
    112             finish();
    113             return;
    114         }
    115         // If we can't get the current system audio mode status, just try to turn on/off system
    116         // audio mode according to the system audio control setting.
    117         addAndStartAction(new SystemAudioActionFromTv(tv(), mAvrAddress,
    118                 tv().isSystemAudioControlFeatureEnabled(), null));
    119         finish();
    120     }
    121 
    122     private boolean canChangeSystemAudio() {
    123         return !(tv().hasAction(SystemAudioActionFromTv.class)
    124                || tv().hasAction(SystemAudioActionFromAvr.class));
    125     }
    126 }
    127