Loading services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +17 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,8 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { HdmiCecLocalDeviceTv(HdmiControlService service) { super(service, HdmiCec.DEVICE_TV); // TODO: load system audio mode and set it to mSystemAudioMode. } @Override Loading Loading @@ -174,6 +176,15 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { } addAndStartAction(new HotplugDetectionAction(HdmiCecLocalDeviceTv.this)); // If there is AVR, initiate System Audio Auto initiation action, // which turns on and off system audio according to last system // audio setting. HdmiCecDeviceInfo avrInfo = getAvrDeviceInfo(); if (avrInfo != null) { addAndStartAction(new SystemAudioAutoInitiationAction( HdmiCecLocalDeviceTv.this, avrInfo.getLogicalAddress())); } } }); addAndStartAction(action); Loading Loading @@ -456,4 +467,10 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { hotplugActions.get(0).pollAllDevicesNow(); } } boolean canChangeSystemAudio() { // TODO: implement this. // return true if no system audio control sequence is running. return false; } } services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java +11 −0 Original line number Diff line number Diff line Loading @@ -377,6 +377,17 @@ public class HdmiCecMessageBuilder { return buildCommand(src, dest, HdmiCec.MESSAGE_USER_CONTROL_RELEASED); } /** * Build <Give System Audio Mode Status> command. * * @param src source address of command * @param dest destination address of command * @return newly created {@link HdmiCecMessage} */ static HdmiCecMessage buildGiveSystemAudioModeStatus(int src, int dest) { return buildCommand(src, dest, HdmiCec.MESSAGE_GIVE_SYSTEM_AUDIO_MODE_STATUS); } /***** Please ADD new buildXXX() methods above. ******/ /** Loading services/core/java/com/android/server/hdmi/HdmiConstants.java +2 −0 Original line number Diff line number Diff line Loading @@ -95,5 +95,7 @@ final class HdmiConstants { static final int POLL_ITERATION_IN_ORDER = 0x10000; static final int POLL_ITERATION_REVERSE_ORDER = 0x20000; static final int UNKNOWN_VOLUME = -1; private HdmiConstants() { /* cannot be instantiated */ } } services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java 0 → 100644 +120 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.hdmi; import android.hardware.hdmi.HdmiCec; import android.hardware.hdmi.HdmiCecMessage; import com.android.server.hdmi.HdmiControlService.SendMessageCallback; /** * Action to initiate system audio once AVR is detected on Device discovery action. */ final class SystemAudioAutoInitiationAction extends FeatureAction { private final int mAvrAddress; // State that waits for <System Audio Mode Status> once send // <Give System Audio Mode Status> to AV Receiver. private static final int STATE_WAITING_FOR_SYSTEM_AUDIO_MODE_STATUS = 1; SystemAudioAutoInitiationAction(HdmiCecLocalDevice source, int avrAddress) { super(source); mAvrAddress = avrAddress; } @Override boolean start() { mState = STATE_WAITING_FOR_SYSTEM_AUDIO_MODE_STATUS; addTimer(mState, TIMEOUT_MS); sendGiveSystemAudioModeStatus(); return true; } private void sendGiveSystemAudioModeStatus() { sendCommand(HdmiCecMessageBuilder.buildGiveSystemAudioModeStatus(getSourceAddress(), mAvrAddress), new SendMessageCallback() { @Override public void onSendCompleted(int error) { if (error != HdmiConstants.SEND_RESULT_SUCCESS) { tv().setSystemAudioMode(false); finish(); } } }); } @Override boolean processCommand(HdmiCecMessage cmd) { if (mState != STATE_WAITING_FOR_SYSTEM_AUDIO_MODE_STATUS) { return false; } switch (cmd.getOpcode()) { case HdmiCec.MESSAGE_SYSTEM_AUDIO_MODE_STATUS: handleSystemAudioModeStatusMessage(); return true; default: return false; } } private void handleSystemAudioModeStatusMessage() { // If the last setting is system audio, turn on system audio whatever AVR status is. if (tv().getSystemAudioMode()) { if (canChangeSystemAudio()) { addAndStartAction(new SystemAudioActionFromTv(tv(), mAvrAddress, true)); } } else { // If the last setting is non-system audio, turn off system audio mode // and update system audio status (volume or mute). tv().setSystemAudioMode(false); if (canChangeSystemAudio()) { addAndStartAction(new SystemAudioStatusAction(tv(), mAvrAddress)); } } finish(); } @Override void handleTimerEvent(int state) { if (mState != state) { return; } switch (mState) { case STATE_WAITING_FOR_SYSTEM_AUDIO_MODE_STATUS: handleSystemAudioModeStatusTimeout(); break; } } private void handleSystemAudioModeStatusTimeout() { if (tv().getSystemAudioMode()) { if (canChangeSystemAudio()) { addAndStartAction(new SystemAudioActionFromTv(tv(), mAvrAddress, true)); } } else { tv().setSystemAudioMode(false); } finish(); } private boolean canChangeSystemAudio() { return tv().canChangeSystemAudio(); } } services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java 0 → 100644 +123 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.hdmi; import android.hardware.hdmi.HdmiCec; import android.hardware.hdmi.HdmiCecMessage; import android.util.Slog; import com.android.server.hdmi.HdmiControlService.SendMessageCallback; /** * Action to update audio status (volume or mute) of audio amplifier */ // TODO: refactor SystemAudioMode so that it uses this class instead of internal state. final class SystemAudioStatusAction extends FeatureAction { private static final String TAG = "SystemAudioStatusAction"; // State that waits for <ReportAudioStatus>. private static final int STATE_WAIT_FOR_REPORT_AUDIO_STATUS = 1; private final int mAvrAddress; SystemAudioStatusAction(HdmiCecLocalDevice source, int avrAddress) { super(source); mAvrAddress = avrAddress; } @Override boolean start() { mState = STATE_WAIT_FOR_REPORT_AUDIO_STATUS; addTimer(mState, TIMEOUT_MS); sendGiveAudioStatus(); return true; } private void sendGiveAudioStatus() { sendCommand(HdmiCecMessageBuilder.buildGiveAudioStatus(getSourceAddress(), mAvrAddress), new SendMessageCallback() { @Override public void onSendCompleted(int error) { if (error != HdmiConstants.SEND_RESULT_SUCCESS) { handleSendGiveAudioStatusFailure(); } } }); } private void handleSendGiveAudioStatusFailure() { // Inform to all application that the audio status (volumn, mute) of // the audio amplifier is unknown. tv().setAudioStatus(false, HdmiConstants.UNKNOWN_VOLUME); int uiCommand = tv().getSystemAudioMode() ? HdmiConstants.UI_COMMAND_RESTORE_VOLUME_FUNCTION // SystemAudioMode: ON : HdmiConstants.UI_COMMAND_MUTE_FUNCTION; // SystemAudioMode: OFF sendUserControlPressedAndReleased(uiCommand); finish(); } private void sendUserControlPressedAndReleased(int uiCommand) { sendCommand(HdmiCecMessageBuilder.buildUserControlPressed( getSourceAddress(), mAvrAddress, uiCommand)); sendCommand(HdmiCecMessageBuilder.buildUserControlReleased( getSourceAddress(), mAvrAddress)); } @Override boolean processCommand(HdmiCecMessage cmd) { if (mState != STATE_WAIT_FOR_REPORT_AUDIO_STATUS) { return false; } switch (cmd.getOpcode()) { case HdmiCec.MESSAGE_REPORT_AUDIO_STATUS: handleReportAudioStatus(cmd); return true; } return false; } private void handleReportAudioStatus(HdmiCecMessage cmd) { byte[] params = cmd.getParams(); if (params.length > 0) { boolean mute = (params[0] & 0x80) == 0x80; int volume = params[0] & 0x7F; tv().setAudioStatus(mute, volume); if ((tv().getSystemAudioMode() && mute) || (!tv().getSystemAudioMode() && !mute)) { // Toggle AVR's mute status to match with the system audio status. sendUserControlPressedAndReleased(HdmiConstants.UI_COMMAND_MUTE); } finish(); } else { Slog.e(TAG, "Invalid <Report Audio Status> message:" + cmd); handleSendGiveAudioStatusFailure(); return; } } @Override void handleTimerEvent(int state) { if (mState != state) { return; } handleSendGiveAudioStatusFailure(); } } Loading
services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +17 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,8 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { HdmiCecLocalDeviceTv(HdmiControlService service) { super(service, HdmiCec.DEVICE_TV); // TODO: load system audio mode and set it to mSystemAudioMode. } @Override Loading Loading @@ -174,6 +176,15 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { } addAndStartAction(new HotplugDetectionAction(HdmiCecLocalDeviceTv.this)); // If there is AVR, initiate System Audio Auto initiation action, // which turns on and off system audio according to last system // audio setting. HdmiCecDeviceInfo avrInfo = getAvrDeviceInfo(); if (avrInfo != null) { addAndStartAction(new SystemAudioAutoInitiationAction( HdmiCecLocalDeviceTv.this, avrInfo.getLogicalAddress())); } } }); addAndStartAction(action); Loading Loading @@ -456,4 +467,10 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { hotplugActions.get(0).pollAllDevicesNow(); } } boolean canChangeSystemAudio() { // TODO: implement this. // return true if no system audio control sequence is running. return false; } }
services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java +11 −0 Original line number Diff line number Diff line Loading @@ -377,6 +377,17 @@ public class HdmiCecMessageBuilder { return buildCommand(src, dest, HdmiCec.MESSAGE_USER_CONTROL_RELEASED); } /** * Build <Give System Audio Mode Status> command. * * @param src source address of command * @param dest destination address of command * @return newly created {@link HdmiCecMessage} */ static HdmiCecMessage buildGiveSystemAudioModeStatus(int src, int dest) { return buildCommand(src, dest, HdmiCec.MESSAGE_GIVE_SYSTEM_AUDIO_MODE_STATUS); } /***** Please ADD new buildXXX() methods above. ******/ /** Loading
services/core/java/com/android/server/hdmi/HdmiConstants.java +2 −0 Original line number Diff line number Diff line Loading @@ -95,5 +95,7 @@ final class HdmiConstants { static final int POLL_ITERATION_IN_ORDER = 0x10000; static final int POLL_ITERATION_REVERSE_ORDER = 0x20000; static final int UNKNOWN_VOLUME = -1; private HdmiConstants() { /* cannot be instantiated */ } }
services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java 0 → 100644 +120 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.hdmi; import android.hardware.hdmi.HdmiCec; import android.hardware.hdmi.HdmiCecMessage; import com.android.server.hdmi.HdmiControlService.SendMessageCallback; /** * Action to initiate system audio once AVR is detected on Device discovery action. */ final class SystemAudioAutoInitiationAction extends FeatureAction { private final int mAvrAddress; // State that waits for <System Audio Mode Status> once send // <Give System Audio Mode Status> to AV Receiver. private static final int STATE_WAITING_FOR_SYSTEM_AUDIO_MODE_STATUS = 1; SystemAudioAutoInitiationAction(HdmiCecLocalDevice source, int avrAddress) { super(source); mAvrAddress = avrAddress; } @Override boolean start() { mState = STATE_WAITING_FOR_SYSTEM_AUDIO_MODE_STATUS; addTimer(mState, TIMEOUT_MS); sendGiveSystemAudioModeStatus(); return true; } private void sendGiveSystemAudioModeStatus() { sendCommand(HdmiCecMessageBuilder.buildGiveSystemAudioModeStatus(getSourceAddress(), mAvrAddress), new SendMessageCallback() { @Override public void onSendCompleted(int error) { if (error != HdmiConstants.SEND_RESULT_SUCCESS) { tv().setSystemAudioMode(false); finish(); } } }); } @Override boolean processCommand(HdmiCecMessage cmd) { if (mState != STATE_WAITING_FOR_SYSTEM_AUDIO_MODE_STATUS) { return false; } switch (cmd.getOpcode()) { case HdmiCec.MESSAGE_SYSTEM_AUDIO_MODE_STATUS: handleSystemAudioModeStatusMessage(); return true; default: return false; } } private void handleSystemAudioModeStatusMessage() { // If the last setting is system audio, turn on system audio whatever AVR status is. if (tv().getSystemAudioMode()) { if (canChangeSystemAudio()) { addAndStartAction(new SystemAudioActionFromTv(tv(), mAvrAddress, true)); } } else { // If the last setting is non-system audio, turn off system audio mode // and update system audio status (volume or mute). tv().setSystemAudioMode(false); if (canChangeSystemAudio()) { addAndStartAction(new SystemAudioStatusAction(tv(), mAvrAddress)); } } finish(); } @Override void handleTimerEvent(int state) { if (mState != state) { return; } switch (mState) { case STATE_WAITING_FOR_SYSTEM_AUDIO_MODE_STATUS: handleSystemAudioModeStatusTimeout(); break; } } private void handleSystemAudioModeStatusTimeout() { if (tv().getSystemAudioMode()) { if (canChangeSystemAudio()) { addAndStartAction(new SystemAudioActionFromTv(tv(), mAvrAddress, true)); } } else { tv().setSystemAudioMode(false); } finish(); } private boolean canChangeSystemAudio() { return tv().canChangeSystemAudio(); } }
services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java 0 → 100644 +123 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.hdmi; import android.hardware.hdmi.HdmiCec; import android.hardware.hdmi.HdmiCecMessage; import android.util.Slog; import com.android.server.hdmi.HdmiControlService.SendMessageCallback; /** * Action to update audio status (volume or mute) of audio amplifier */ // TODO: refactor SystemAudioMode so that it uses this class instead of internal state. final class SystemAudioStatusAction extends FeatureAction { private static final String TAG = "SystemAudioStatusAction"; // State that waits for <ReportAudioStatus>. private static final int STATE_WAIT_FOR_REPORT_AUDIO_STATUS = 1; private final int mAvrAddress; SystemAudioStatusAction(HdmiCecLocalDevice source, int avrAddress) { super(source); mAvrAddress = avrAddress; } @Override boolean start() { mState = STATE_WAIT_FOR_REPORT_AUDIO_STATUS; addTimer(mState, TIMEOUT_MS); sendGiveAudioStatus(); return true; } private void sendGiveAudioStatus() { sendCommand(HdmiCecMessageBuilder.buildGiveAudioStatus(getSourceAddress(), mAvrAddress), new SendMessageCallback() { @Override public void onSendCompleted(int error) { if (error != HdmiConstants.SEND_RESULT_SUCCESS) { handleSendGiveAudioStatusFailure(); } } }); } private void handleSendGiveAudioStatusFailure() { // Inform to all application that the audio status (volumn, mute) of // the audio amplifier is unknown. tv().setAudioStatus(false, HdmiConstants.UNKNOWN_VOLUME); int uiCommand = tv().getSystemAudioMode() ? HdmiConstants.UI_COMMAND_RESTORE_VOLUME_FUNCTION // SystemAudioMode: ON : HdmiConstants.UI_COMMAND_MUTE_FUNCTION; // SystemAudioMode: OFF sendUserControlPressedAndReleased(uiCommand); finish(); } private void sendUserControlPressedAndReleased(int uiCommand) { sendCommand(HdmiCecMessageBuilder.buildUserControlPressed( getSourceAddress(), mAvrAddress, uiCommand)); sendCommand(HdmiCecMessageBuilder.buildUserControlReleased( getSourceAddress(), mAvrAddress)); } @Override boolean processCommand(HdmiCecMessage cmd) { if (mState != STATE_WAIT_FOR_REPORT_AUDIO_STATUS) { return false; } switch (cmd.getOpcode()) { case HdmiCec.MESSAGE_REPORT_AUDIO_STATUS: handleReportAudioStatus(cmd); return true; } return false; } private void handleReportAudioStatus(HdmiCecMessage cmd) { byte[] params = cmd.getParams(); if (params.length > 0) { boolean mute = (params[0] & 0x80) == 0x80; int volume = params[0] & 0x7F; tv().setAudioStatus(mute, volume); if ((tv().getSystemAudioMode() && mute) || (!tv().getSystemAudioMode() && !mute)) { // Toggle AVR's mute status to match with the system audio status. sendUserControlPressedAndReleased(HdmiConstants.UI_COMMAND_MUTE); } finish(); } else { Slog.e(TAG, "Invalid <Report Audio Status> message:" + cmd); handleSendGiveAudioStatusFailure(); return; } } @Override void handleTimerEvent(int state) { if (mState != state) { return; } handleSendGiveAudioStatusFailure(); } }