Loading services/core/java/com/android/server/hdmi/DetectTvSystemAudioModeSupportAction.java 0 → 100644 +88 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 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.tv.cec.V1_0.SendMessageResult; import com.android.server.hdmi.HdmiCecLocalDeviceAudioSystem.TvSystemAudioModeSupportedCallback; /** * Feature action that detects if TV supports system audio control. */ public class DetectTvSystemAudioModeSupportAction extends HdmiCecFeatureAction { // State that waits for <Active Source> once send <Request Active Source>. private static final int STATE_WAITING_FOR_FEATURE_ABORT = 1; private TvSystemAudioModeSupportedCallback mCallback; private int mState; DetectTvSystemAudioModeSupportAction(HdmiCecLocalDevice source, TvSystemAudioModeSupportedCallback callback) { super(source); mCallback = callback; } @Override boolean start() { mState = STATE_WAITING_FOR_FEATURE_ABORT; addTimer(mState, HdmiConfig.TIMEOUT_MS); sendSetSystemAudioMode(); return true; } @Override boolean processCommand(HdmiCecMessage cmd) { if (cmd.getOpcode() == Constants.MESSAGE_FEATURE_ABORT) { if (mState != STATE_WAITING_FOR_FEATURE_ABORT) { return false; } finishAction(false); return true; } return false; } @Override void handleTimerEvent(int state) { if (mState != state) { return; } switch (mState) { case STATE_WAITING_FOR_FEATURE_ABORT: finishAction(true); break; } } protected void sendSetSystemAudioMode() { sendCommand( HdmiCecMessageBuilder.buildSetSystemAudioMode(getSourceAddress(),Constants.ADDR_TV, true), result -> { if (result != SendMessageResult.SUCCESS) { finishAction(false); } }); } private void finishAction(boolean supported) { mCallback.onResult(supported); audioSystem().setTvSystemAudioModeSupport(supported); finish(); } } services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java +12 −4 Original line number Diff line number Diff line Loading @@ -15,7 +15,6 @@ */ package com.android.server.hdmi; import static com.android.server.hdmi.Constants.ADDR_TV; import static com.android.server.hdmi.Constants.ALWAYS_SYSTEM_AUDIO_CONTROL_ON_POWER_ON; import static com.android.server.hdmi.Constants.PROPERTY_SYSTEM_AUDIO_CONTROL_ON_POWER_ON; import static com.android.server.hdmi.Constants.USE_LAST_STATE_SYSTEM_AUDIO_CONTROL_ON_POWER_ON; Loading @@ -23,7 +22,6 @@ import static com.android.server.hdmi.Constants.USE_LAST_STATE_SYSTEM_AUDIO_CONT import android.hardware.hdmi.HdmiDeviceInfo; import android.media.AudioManager; import android.os.SystemProperties; import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly; Loading @@ -46,6 +44,8 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDevice { private boolean mSystemAudioControlFeatureEnabled; protected Integer mSystemAudioSource; private boolean mTvSystemAudioModeSupport; protected HdmiCecLocalDeviceAudioSystem(HdmiControlService service) { super(service, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); mSystemAudioControlFeatureEnabled = true; Loading @@ -58,6 +58,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDevice { @ServiceThreadOnly protected void onStandby(boolean initiatedByCec, int standbyAction) { assertRunOnServiceThread(); mTvSystemAudioModeSupport = false; // Record the last state of System Audio Control before going to standby synchronized (mLock) { SystemProperties.set(Constants.PROPERTY_LAST_SYSTEM_AUDIO_CONTROL, Loading Loading @@ -312,7 +313,14 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDevice { * its physical address. */ void queryTvSystemAudioModeSupport(TvSystemAudioModeSupportedCallback callback) { // TODO(b/80297382): implement detect TV for system audio mode support. if (!mTvSystemAudioModeSupport) { addAndStartAction(new DetectTvSystemAudioModeSupportAction(this, callback)); } else { callback.onResult(true); } } void setTvSystemAudioModeSupport(boolean supported) { mTvSystemAudioModeSupport = supported; } } services/tests/servicestests/src/com/android/server/hdmi/DetectTvSystemAudioModeSupportActionTest.java 0 → 100644 +140 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 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 static org.junit.Assert.assertEquals; import android.annotation.Nullable; import android.hardware.hdmi.HdmiDeviceInfo; import android.hardware.tv.cec.V1_0.SendMessageResult; import android.os.Looper; import android.os.test.TestLooper; import android.support.test.filters.SmallTest; import com.android.server.hdmi.HdmiCecLocalDeviceAudioSystem.TvSystemAudioModeSupportedCallback; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; /** * Tests for {@link DetectTvSystemAudioModeSupportAction} class. */ @SmallTest @RunWith(JUnit4.class) public class DetectTvSystemAudioModeSupportActionTest { private HdmiDeviceInfo mDeviceInfoForTests; private HdmiCecLocalDeviceAudioSystem mHdmiCecLocalDeviceAudioSystem; private DetectTvSystemAudioModeSupportAction mAction; private TestLooper mTestLooper = new TestLooper(); private boolean mSendCecCommandSuccess; private boolean mShouldDispatchFeatureAbort; private Boolean mSupported; @Before public void SetUp() { mDeviceInfoForTests = new HdmiDeviceInfo(1001, 1234); HdmiControlService hdmiControlService = new HdmiControlService(null) { @Override void sendCecCommand(HdmiCecMessage command, @Nullable SendMessageCallback callback) { switch (command.getOpcode()) { case Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE: if (callback != null) { callback.onSendCompleted(mSendCecCommandSuccess ? SendMessageResult.SUCCESS : SendMessageResult.NACK); } if (mShouldDispatchFeatureAbort) { mHdmiCecLocalDeviceAudioSystem.dispatchMessage( HdmiCecMessageBuilder.buildFeatureAbortCommand( Constants.ADDR_TV, mHdmiCecLocalDeviceAudioSystem.mAddress, Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE, Constants.ABORT_UNRECOGNIZED_OPCODE)); } break; default: throw new IllegalArgumentException("Unexpected message"); } } @Override boolean isPowerStandby() { return false; } @Override boolean isAddressAllocated() { return true; } @Override Looper getServiceLooper() { return mTestLooper.getLooper(); } }; mHdmiCecLocalDeviceAudioSystem = new HdmiCecLocalDeviceAudioSystem(hdmiControlService) { @Override HdmiDeviceInfo getDeviceInfo() { return mDeviceInfoForTests; } }; mHdmiCecLocalDeviceAudioSystem.init(); Looper looper = mTestLooper.getLooper(); hdmiControlService.setIoLooper(looper); mAction = new DetectTvSystemAudioModeSupportAction( mHdmiCecLocalDeviceAudioSystem, new TvSystemAudioModeSupportedCallback() { public void onResult(boolean supported) { mSupported = Boolean.valueOf(supported); } }); mSupported = null; } @Test public void testSendCecCommandNotSucceed() { mSendCecCommandSuccess = false; mShouldDispatchFeatureAbort = false; mHdmiCecLocalDeviceAudioSystem.addAndStartAction(mAction); mTestLooper.dispatchAll(); assertEquals(Boolean.FALSE, mSupported); } @Test public void testFeatureAbort() { mSendCecCommandSuccess = true; mShouldDispatchFeatureAbort = true; mHdmiCecLocalDeviceAudioSystem.addAndStartAction(mAction); mTestLooper.dispatchAll(); assertEquals(Boolean.FALSE, mSupported); } @Test public void testSupported() { mSendCecCommandSuccess = true; mShouldDispatchFeatureAbort = false; mHdmiCecLocalDeviceAudioSystem.addAndStartAction(mAction); mTestLooper.moveTimeForward(2000); mTestLooper.dispatchAll(); assertEquals(Boolean.TRUE, mSupported); } } Loading
services/core/java/com/android/server/hdmi/DetectTvSystemAudioModeSupportAction.java 0 → 100644 +88 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 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.tv.cec.V1_0.SendMessageResult; import com.android.server.hdmi.HdmiCecLocalDeviceAudioSystem.TvSystemAudioModeSupportedCallback; /** * Feature action that detects if TV supports system audio control. */ public class DetectTvSystemAudioModeSupportAction extends HdmiCecFeatureAction { // State that waits for <Active Source> once send <Request Active Source>. private static final int STATE_WAITING_FOR_FEATURE_ABORT = 1; private TvSystemAudioModeSupportedCallback mCallback; private int mState; DetectTvSystemAudioModeSupportAction(HdmiCecLocalDevice source, TvSystemAudioModeSupportedCallback callback) { super(source); mCallback = callback; } @Override boolean start() { mState = STATE_WAITING_FOR_FEATURE_ABORT; addTimer(mState, HdmiConfig.TIMEOUT_MS); sendSetSystemAudioMode(); return true; } @Override boolean processCommand(HdmiCecMessage cmd) { if (cmd.getOpcode() == Constants.MESSAGE_FEATURE_ABORT) { if (mState != STATE_WAITING_FOR_FEATURE_ABORT) { return false; } finishAction(false); return true; } return false; } @Override void handleTimerEvent(int state) { if (mState != state) { return; } switch (mState) { case STATE_WAITING_FOR_FEATURE_ABORT: finishAction(true); break; } } protected void sendSetSystemAudioMode() { sendCommand( HdmiCecMessageBuilder.buildSetSystemAudioMode(getSourceAddress(),Constants.ADDR_TV, true), result -> { if (result != SendMessageResult.SUCCESS) { finishAction(false); } }); } private void finishAction(boolean supported) { mCallback.onResult(supported); audioSystem().setTvSystemAudioModeSupport(supported); finish(); } }
services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java +12 −4 Original line number Diff line number Diff line Loading @@ -15,7 +15,6 @@ */ package com.android.server.hdmi; import static com.android.server.hdmi.Constants.ADDR_TV; import static com.android.server.hdmi.Constants.ALWAYS_SYSTEM_AUDIO_CONTROL_ON_POWER_ON; import static com.android.server.hdmi.Constants.PROPERTY_SYSTEM_AUDIO_CONTROL_ON_POWER_ON; import static com.android.server.hdmi.Constants.USE_LAST_STATE_SYSTEM_AUDIO_CONTROL_ON_POWER_ON; Loading @@ -23,7 +22,6 @@ import static com.android.server.hdmi.Constants.USE_LAST_STATE_SYSTEM_AUDIO_CONT import android.hardware.hdmi.HdmiDeviceInfo; import android.media.AudioManager; import android.os.SystemProperties; import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly; Loading @@ -46,6 +44,8 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDevice { private boolean mSystemAudioControlFeatureEnabled; protected Integer mSystemAudioSource; private boolean mTvSystemAudioModeSupport; protected HdmiCecLocalDeviceAudioSystem(HdmiControlService service) { super(service, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); mSystemAudioControlFeatureEnabled = true; Loading @@ -58,6 +58,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDevice { @ServiceThreadOnly protected void onStandby(boolean initiatedByCec, int standbyAction) { assertRunOnServiceThread(); mTvSystemAudioModeSupport = false; // Record the last state of System Audio Control before going to standby synchronized (mLock) { SystemProperties.set(Constants.PROPERTY_LAST_SYSTEM_AUDIO_CONTROL, Loading Loading @@ -312,7 +313,14 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDevice { * its physical address. */ void queryTvSystemAudioModeSupport(TvSystemAudioModeSupportedCallback callback) { // TODO(b/80297382): implement detect TV for system audio mode support. if (!mTvSystemAudioModeSupport) { addAndStartAction(new DetectTvSystemAudioModeSupportAction(this, callback)); } else { callback.onResult(true); } } void setTvSystemAudioModeSupport(boolean supported) { mTvSystemAudioModeSupport = supported; } }
services/tests/servicestests/src/com/android/server/hdmi/DetectTvSystemAudioModeSupportActionTest.java 0 → 100644 +140 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 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 static org.junit.Assert.assertEquals; import android.annotation.Nullable; import android.hardware.hdmi.HdmiDeviceInfo; import android.hardware.tv.cec.V1_0.SendMessageResult; import android.os.Looper; import android.os.test.TestLooper; import android.support.test.filters.SmallTest; import com.android.server.hdmi.HdmiCecLocalDeviceAudioSystem.TvSystemAudioModeSupportedCallback; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; /** * Tests for {@link DetectTvSystemAudioModeSupportAction} class. */ @SmallTest @RunWith(JUnit4.class) public class DetectTvSystemAudioModeSupportActionTest { private HdmiDeviceInfo mDeviceInfoForTests; private HdmiCecLocalDeviceAudioSystem mHdmiCecLocalDeviceAudioSystem; private DetectTvSystemAudioModeSupportAction mAction; private TestLooper mTestLooper = new TestLooper(); private boolean mSendCecCommandSuccess; private boolean mShouldDispatchFeatureAbort; private Boolean mSupported; @Before public void SetUp() { mDeviceInfoForTests = new HdmiDeviceInfo(1001, 1234); HdmiControlService hdmiControlService = new HdmiControlService(null) { @Override void sendCecCommand(HdmiCecMessage command, @Nullable SendMessageCallback callback) { switch (command.getOpcode()) { case Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE: if (callback != null) { callback.onSendCompleted(mSendCecCommandSuccess ? SendMessageResult.SUCCESS : SendMessageResult.NACK); } if (mShouldDispatchFeatureAbort) { mHdmiCecLocalDeviceAudioSystem.dispatchMessage( HdmiCecMessageBuilder.buildFeatureAbortCommand( Constants.ADDR_TV, mHdmiCecLocalDeviceAudioSystem.mAddress, Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE, Constants.ABORT_UNRECOGNIZED_OPCODE)); } break; default: throw new IllegalArgumentException("Unexpected message"); } } @Override boolean isPowerStandby() { return false; } @Override boolean isAddressAllocated() { return true; } @Override Looper getServiceLooper() { return mTestLooper.getLooper(); } }; mHdmiCecLocalDeviceAudioSystem = new HdmiCecLocalDeviceAudioSystem(hdmiControlService) { @Override HdmiDeviceInfo getDeviceInfo() { return mDeviceInfoForTests; } }; mHdmiCecLocalDeviceAudioSystem.init(); Looper looper = mTestLooper.getLooper(); hdmiControlService.setIoLooper(looper); mAction = new DetectTvSystemAudioModeSupportAction( mHdmiCecLocalDeviceAudioSystem, new TvSystemAudioModeSupportedCallback() { public void onResult(boolean supported) { mSupported = Boolean.valueOf(supported); } }); mSupported = null; } @Test public void testSendCecCommandNotSucceed() { mSendCecCommandSuccess = false; mShouldDispatchFeatureAbort = false; mHdmiCecLocalDeviceAudioSystem.addAndStartAction(mAction); mTestLooper.dispatchAll(); assertEquals(Boolean.FALSE, mSupported); } @Test public void testFeatureAbort() { mSendCecCommandSuccess = true; mShouldDispatchFeatureAbort = true; mHdmiCecLocalDeviceAudioSystem.addAndStartAction(mAction); mTestLooper.dispatchAll(); assertEquals(Boolean.FALSE, mSupported); } @Test public void testSupported() { mSendCecCommandSuccess = true; mShouldDispatchFeatureAbort = false; mHdmiCecLocalDeviceAudioSystem.addAndStartAction(mAction); mTestLooper.moveTimeForward(2000); mTestLooper.dispatchAll(); assertEquals(Boolean.TRUE, mSupported); } }