diff options
| author | Jungshik Jang <jayjang@google.com> | 2014-06-18 02:38:11 +0000 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-06-17 22:26:08 +0000 |
| commit | bce527139a9fe80a8195a4fc787759ff27da8d27 (patch) | |
| tree | b31815e022a63aeff48d089564641688721a0b58 /services/core | |
| parent | 128be2a919d2915a1a677cddb3a2e93617dc4d0b (diff) | |
| parent | 187d01765b935d07936f74343b4f4af590c239a1 (diff) | |
| download | frameworks_base-bce527139a9fe80a8195a4fc787759ff27da8d27.zip frameworks_base-bce527139a9fe80a8195a4fc787759ff27da8d27.tar.gz frameworks_base-bce527139a9fe80a8195a4fc787759ff27da8d27.tar.bz2 | |
Merge "Add SystemAudioAutoInitiationAction and SystemAudioStatusAction"
Diffstat (limited to 'services/core')
5 files changed, 273 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java index 92ddd3d..18a3bbf 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java @@ -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 @@ -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); @@ -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; + } } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java index 8dbfd85..361a063 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java @@ -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. ******/ /** diff --git a/services/core/java/com/android/server/hdmi/HdmiConstants.java b/services/core/java/com/android/server/hdmi/HdmiConstants.java index 9c60e55..5294506 100644 --- a/services/core/java/com/android/server/hdmi/HdmiConstants.java +++ b/services/core/java/com/android/server/hdmi/HdmiConstants.java @@ -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 */ } } diff --git a/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java b/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java new file mode 100644 index 0000000..e4d82ef --- /dev/null +++ b/services/core/java/com/android/server/hdmi/SystemAudioAutoInitiationAction.java @@ -0,0 +1,120 @@ +/* + * 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(); + } +} diff --git a/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java b/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java new file mode 100644 index 0000000..75e4fef --- /dev/null +++ b/services/core/java/com/android/server/hdmi/SystemAudioStatusAction.java @@ -0,0 +1,123 @@ +/* + * 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(); + } +} |
