Loading services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +25 −1 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import android.view.KeyEvent; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.IndentingPrintWriter; import com.android.server.hdmi.Constants.LocalActivePort; import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly; import com.android.server.hdmi.HdmiControlService.SendMessageCallback; Loading Loading @@ -1051,7 +1052,7 @@ abstract class HdmiCecLocalDevice { * <p>This check assumes target address is valid. * @param targetPhysicalAddress is the physical address of the target device * @return * <p>If the target device is under the current device, return the port number of current device * If the target device is under the current device, return the port number of current device * that the target device is connected to. * * <p>If the target device has the same physical address as the current device, return Loading Loading @@ -1085,4 +1086,27 @@ abstract class HdmiCecLocalDevice { } return TARGET_NOT_UNDER_LOCAL_DEVICE; } /** Calculates the physical address for {@code activePortId}. * * <p>This method assumes current device physical address is valid. * <p>If the current device is already the leaf of the whole CEC system * and can't have devices under it, will return its own physical address. * * @param activePortId is the local active port Id * @return the calculated physical address of the port */ protected int getActivePathOnSwitchFromActivePortId(@LocalActivePort int activePortId) { int myPhysicalAddress = mService.getPhysicalAddress(); int finalMask = activePortId << 8; int mask; for (mask = 0x0F00; mask > 0x000F; mask >>= 4) { if ((myPhysicalAddress & mask) == 0) { break; } else { finalMask >>= 4; } } return finalMask | myPhysicalAddress; } } services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java +55 −0 Original line number Diff line number Diff line Loading @@ -677,4 +677,59 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { | Intent.FLAG_ACTIVITY_NO_ANIMATION); mService.getContext().startActivity(activityIntent); } @Override protected void handleRoutingChangeAndInformation(int physicalAddress, HdmiCecMessage message) { int port = getLocalPortFromPhysicalAddress(physicalAddress); // Routing change or information sent from switches under the current device can be ignored. if (port > 0) { return; } // When other switches route to some other devices not under the current device, // check system audio mode status and do ARC switch if needed. if (port < 0 && isSystemAudioActivated()) { handleRoutingChangeAndInformationForSystemAudio(); return; } // When other switches route to the current device // and the current device is also a switch. if (port == 0) { handleRoutingChangeAndInformationForSwitch(message); } } // Handle the system audio(ARC) part of the logic on receiving routing change or information. private void handleRoutingChangeAndInformationForSystemAudio() { if (mService.isPowerStandbyOrTransient()) { mService.wakeUp(); } // TODO(b/115637145): handle system aduio without ARC routeToInputFromPortId(Constants.CEC_SWITCH_ARC); } // Handle the routing control part of the logic on receiving routing change or information. private void handleRoutingChangeAndInformationForSwitch(HdmiCecMessage message) { if (mService.isPowerStandbyOrTransient()) { mService.wakeUp(); } if (getLocalActivePort() == Constants.CEC_SWITCH_HOME && mService.isPlaybackDevice()) { routeToInputFromPortId(Constants.CEC_SWITCH_HOME); setAndBroadcastActiveSource(message, mService.getPhysicalAddress()); return; } int routingInformationPath = getActivePathOnSwitchFromActivePortId(mService.getPhysicalAddress()); // If current device is already the leaf of the whole HDMI system, will do nothing. if (routingInformationPath == mService.getPhysicalAddress()) { HdmiLogger.debug("Current device can't assign valid physical address" + "to devices under it any more. " + "It's physical address is " + routingInformationPath); return; } // Otherwise will switch to the current active port and broadcast routing information. mService.sendCecCommand(HdmiCecMessageBuilder.buildRoutingInformation( mAddress, routingInformationPath)); routeToInputFromPortId(getActivePortId()); } } services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java +36 −0 Original line number Diff line number Diff line Loading @@ -143,12 +143,48 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice { return true; } @Override @ServiceThreadOnly protected boolean handleRoutingChange(HdmiCecMessage message) { assertRunOnServiceThread(); int newPath = HdmiUtils.twoBytesToInt(message.getParams(), 2); // if the current device is a pure playback device if (!mIsSwitchDevice && newPath == mService.getPhysicalAddress() && mService.isPlaybackDevice()) { setAndBroadcastActiveSource(message, newPath); } handleRoutingChangeAndInformation(newPath, message); return true; } @Override @ServiceThreadOnly protected boolean handleRoutingInformation(HdmiCecMessage message) { assertRunOnServiceThread(); int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams()); // if the current device is a pure playback device if (!mIsSwitchDevice && physicalAddress == mService.getPhysicalAddress() && mService.isPlaybackDevice()) { setAndBroadcastActiveSource(message, physicalAddress); } handleRoutingChangeAndInformation(physicalAddress, message); return true; } // Method to switch Input with the new Active Path. // All the devices with Switch functionality should implement this. protected void switchInputOnReceivingNewActivePath(int physicalAddress) { // do nothing } // Source device with Switch functionality should implement this method. // TODO(): decide which type will handle the routing when multi device type is supported protected void handleRoutingChangeAndInformation(int physicalAddress, HdmiCecMessage message) { // do nothing } // Active source claiming needs to be handled in the parent class // since we decide who will be the active source when the device supports // multiple device types in this method. Loading services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java +32 −0 Original line number Diff line number Diff line Loading @@ -571,4 +571,36 @@ public class HdmiCecLocalDeviceAudioSystemTest { assertThat(mHdmiCecLocalDeviceAudioSystem.getActiveSource()) .isEqualTo(expectedActiveSource); } @Test public void handleRoutingChange_currentActivePortIsHome() { HdmiCecMessage message = HdmiCecMessageBuilder.buildRoutingChange(ADDR_TV, 0x3000, mAvrPhysicalAddress); HdmiCecMessage expectedMessage = HdmiCecMessageBuilder.buildActiveSource(ADDR_AUDIO_SYSTEM, mAvrPhysicalAddress); ActiveSource expectedActiveSource = ActiveSource.of(ADDR_AUDIO_SYSTEM, mAvrPhysicalAddress); int expectedLocalActivePort = Constants.CEC_SWITCH_HOME; assertThat(mHdmiCecLocalDeviceAudioSystem.handleRoutingChange(message)).isTrue(); mTestLooper.dispatchAll(); assertThat(mHdmiCecLocalDeviceAudioSystem.getActiveSource()) .isEqualTo(expectedActiveSource); assertThat(mHdmiCecLocalDeviceAudioSystem.getLocalActivePort()) .isEqualTo(expectedLocalActivePort); assertThat(mNativeWrapper.getOnlyResultMessage()).isEqualTo(expectedMessage); } @Test public void handleRoutingInformation_currentActivePortIsHDMI1() { HdmiCecMessage message = HdmiCecMessageBuilder.buildRoutingInformation(ADDR_TV, 0x2000); mHdmiCecLocalDeviceAudioSystem.setLocalActivePort(Constants.CEC_SWITCH_HDMI1); HdmiCecMessage expectedMessage = HdmiCecMessageBuilder.buildRoutingInformation(ADDR_AUDIO_SYSTEM, 0x2100); assertThat(mHdmiCecLocalDeviceAudioSystem.handleRoutingInformation(message)).isTrue(); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getOnlyResultMessage()).isEqualTo(expectedMessage); } } Loading
services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +25 −1 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import android.view.KeyEvent; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.IndentingPrintWriter; import com.android.server.hdmi.Constants.LocalActivePort; import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly; import com.android.server.hdmi.HdmiControlService.SendMessageCallback; Loading Loading @@ -1051,7 +1052,7 @@ abstract class HdmiCecLocalDevice { * <p>This check assumes target address is valid. * @param targetPhysicalAddress is the physical address of the target device * @return * <p>If the target device is under the current device, return the port number of current device * If the target device is under the current device, return the port number of current device * that the target device is connected to. * * <p>If the target device has the same physical address as the current device, return Loading Loading @@ -1085,4 +1086,27 @@ abstract class HdmiCecLocalDevice { } return TARGET_NOT_UNDER_LOCAL_DEVICE; } /** Calculates the physical address for {@code activePortId}. * * <p>This method assumes current device physical address is valid. * <p>If the current device is already the leaf of the whole CEC system * and can't have devices under it, will return its own physical address. * * @param activePortId is the local active port Id * @return the calculated physical address of the port */ protected int getActivePathOnSwitchFromActivePortId(@LocalActivePort int activePortId) { int myPhysicalAddress = mService.getPhysicalAddress(); int finalMask = activePortId << 8; int mask; for (mask = 0x0F00; mask > 0x000F; mask >>= 4) { if ((myPhysicalAddress & mask) == 0) { break; } else { finalMask >>= 4; } } return finalMask | myPhysicalAddress; } }
services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java +55 −0 Original line number Diff line number Diff line Loading @@ -677,4 +677,59 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { | Intent.FLAG_ACTIVITY_NO_ANIMATION); mService.getContext().startActivity(activityIntent); } @Override protected void handleRoutingChangeAndInformation(int physicalAddress, HdmiCecMessage message) { int port = getLocalPortFromPhysicalAddress(physicalAddress); // Routing change or information sent from switches under the current device can be ignored. if (port > 0) { return; } // When other switches route to some other devices not under the current device, // check system audio mode status and do ARC switch if needed. if (port < 0 && isSystemAudioActivated()) { handleRoutingChangeAndInformationForSystemAudio(); return; } // When other switches route to the current device // and the current device is also a switch. if (port == 0) { handleRoutingChangeAndInformationForSwitch(message); } } // Handle the system audio(ARC) part of the logic on receiving routing change or information. private void handleRoutingChangeAndInformationForSystemAudio() { if (mService.isPowerStandbyOrTransient()) { mService.wakeUp(); } // TODO(b/115637145): handle system aduio without ARC routeToInputFromPortId(Constants.CEC_SWITCH_ARC); } // Handle the routing control part of the logic on receiving routing change or information. private void handleRoutingChangeAndInformationForSwitch(HdmiCecMessage message) { if (mService.isPowerStandbyOrTransient()) { mService.wakeUp(); } if (getLocalActivePort() == Constants.CEC_SWITCH_HOME && mService.isPlaybackDevice()) { routeToInputFromPortId(Constants.CEC_SWITCH_HOME); setAndBroadcastActiveSource(message, mService.getPhysicalAddress()); return; } int routingInformationPath = getActivePathOnSwitchFromActivePortId(mService.getPhysicalAddress()); // If current device is already the leaf of the whole HDMI system, will do nothing. if (routingInformationPath == mService.getPhysicalAddress()) { HdmiLogger.debug("Current device can't assign valid physical address" + "to devices under it any more. " + "It's physical address is " + routingInformationPath); return; } // Otherwise will switch to the current active port and broadcast routing information. mService.sendCecCommand(HdmiCecMessageBuilder.buildRoutingInformation( mAddress, routingInformationPath)); routeToInputFromPortId(getActivePortId()); } }
services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceSource.java +36 −0 Original line number Diff line number Diff line Loading @@ -143,12 +143,48 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice { return true; } @Override @ServiceThreadOnly protected boolean handleRoutingChange(HdmiCecMessage message) { assertRunOnServiceThread(); int newPath = HdmiUtils.twoBytesToInt(message.getParams(), 2); // if the current device is a pure playback device if (!mIsSwitchDevice && newPath == mService.getPhysicalAddress() && mService.isPlaybackDevice()) { setAndBroadcastActiveSource(message, newPath); } handleRoutingChangeAndInformation(newPath, message); return true; } @Override @ServiceThreadOnly protected boolean handleRoutingInformation(HdmiCecMessage message) { assertRunOnServiceThread(); int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams()); // if the current device is a pure playback device if (!mIsSwitchDevice && physicalAddress == mService.getPhysicalAddress() && mService.isPlaybackDevice()) { setAndBroadcastActiveSource(message, physicalAddress); } handleRoutingChangeAndInformation(physicalAddress, message); return true; } // Method to switch Input with the new Active Path. // All the devices with Switch functionality should implement this. protected void switchInputOnReceivingNewActivePath(int physicalAddress) { // do nothing } // Source device with Switch functionality should implement this method. // TODO(): decide which type will handle the routing when multi device type is supported protected void handleRoutingChangeAndInformation(int physicalAddress, HdmiCecMessage message) { // do nothing } // Active source claiming needs to be handled in the parent class // since we decide who will be the active source when the device supports // multiple device types in this method. Loading
services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java +32 −0 Original line number Diff line number Diff line Loading @@ -571,4 +571,36 @@ public class HdmiCecLocalDeviceAudioSystemTest { assertThat(mHdmiCecLocalDeviceAudioSystem.getActiveSource()) .isEqualTo(expectedActiveSource); } @Test public void handleRoutingChange_currentActivePortIsHome() { HdmiCecMessage message = HdmiCecMessageBuilder.buildRoutingChange(ADDR_TV, 0x3000, mAvrPhysicalAddress); HdmiCecMessage expectedMessage = HdmiCecMessageBuilder.buildActiveSource(ADDR_AUDIO_SYSTEM, mAvrPhysicalAddress); ActiveSource expectedActiveSource = ActiveSource.of(ADDR_AUDIO_SYSTEM, mAvrPhysicalAddress); int expectedLocalActivePort = Constants.CEC_SWITCH_HOME; assertThat(mHdmiCecLocalDeviceAudioSystem.handleRoutingChange(message)).isTrue(); mTestLooper.dispatchAll(); assertThat(mHdmiCecLocalDeviceAudioSystem.getActiveSource()) .isEqualTo(expectedActiveSource); assertThat(mHdmiCecLocalDeviceAudioSystem.getLocalActivePort()) .isEqualTo(expectedLocalActivePort); assertThat(mNativeWrapper.getOnlyResultMessage()).isEqualTo(expectedMessage); } @Test public void handleRoutingInformation_currentActivePortIsHDMI1() { HdmiCecMessage message = HdmiCecMessageBuilder.buildRoutingInformation(ADDR_TV, 0x2000); mHdmiCecLocalDeviceAudioSystem.setLocalActivePort(Constants.CEC_SWITCH_HDMI1); HdmiCecMessage expectedMessage = HdmiCecMessageBuilder.buildRoutingInformation(ADDR_AUDIO_SYSTEM, 0x2100); assertThat(mHdmiCecLocalDeviceAudioSystem.handleRoutingInformation(message)).isTrue(); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getOnlyResultMessage()).isEqualTo(expectedMessage); } }