Loading services/core/java/com/android/server/hdmi/ActiveSourceHandler.java +21 −18 Original line number Diff line number Diff line Loading @@ -23,6 +23,8 @@ import android.hardware.hdmi.HdmiControlManager; import android.os.RemoteException; import android.util.Slog; import com.android.server.hdmi.HdmiCecLocalDevice.ActiveSource; /** * Handles CEC command <Active Source>. * <p> Loading Loading @@ -54,44 +56,45 @@ final class ActiveSourceHandler { /** * Handles the incoming active source command. * * @param activeAddress logical address of the device to be the active source * @param activePath routing path of the device to be the active source * @param newActive new active source information */ void process(int activeAddress, int activePath) { void process(ActiveSource newActive) { // Seq #17 HdmiCecLocalDeviceTv tv = mSource; if (getSourcePath() == activePath && tv.getActiveSource() == getSourceAddress()) { ActiveSource activeSource = tv.getActiveSource(); if (activeSource.equals(newActive)) { invokeCallback(HdmiControlManager.RESULT_SUCCESS); return; } HdmiCecDeviceInfo device = mService.getDeviceInfo(activeAddress); HdmiCecDeviceInfo device = mService.getDeviceInfo(newActive.logicalAddress); if (device == null) { tv.startNewDeviceAction(activeAddress, activePath); tv.startNewDeviceAction(newActive); } int currentActive = tv.getActiveSource(); int currentPath = tv.getActivePath(); ActiveSource current = tv.getActiveSource(); if (!tv.isProhibitMode()) { tv.updateActiveSource(activeAddress, activePath); if (currentActive != activeAddress && currentPath != activePath) { tv.updateActivePortId(mService.pathToPortId(activePath)); tv.updateActiveSource(newActive); if (!current.equals(newActive)) { boolean notifyInputChange = (mCallback == null); tv.updateActiveInput(newActive.physicalAddress, notifyInputChange); } invokeCallback(HdmiControlManager.RESULT_SUCCESS); } else { // TV is in a mode that should keep its current source/input from // being changed for its operation. Reclaim the active source // or switch the port back to the one used for the current mode. if (currentActive == getSourceAddress()) { HdmiCecMessage activeSource = HdmiCecMessageBuilder.buildActiveSource(currentActive, currentPath); mService.sendCecCommand(activeSource); tv.updateActiveSource(currentActive, currentPath); if (current.logicalAddress == getSourceAddress()) { HdmiCecMessage activeSourceCommand = HdmiCecMessageBuilder.buildActiveSource( current.logicalAddress, current.physicalAddress); mService.sendCecCommand(activeSourceCommand); tv.updateActiveSource(current); invokeCallback(HdmiControlManager.RESULT_SUCCESS); } else { HdmiCecMessage routingChange = HdmiCecMessageBuilder.buildRoutingChange( getSourceAddress(), activePath, currentPath); getSourceAddress(), newActive.physicalAddress, current.physicalAddress); mService.sendCecCommand(routingChange); tv.addAndStartAction(new RoutingControlAction(tv, currentPath, true, mCallback)); tv.addAndStartAction( new RoutingControlAction(tv, current.physicalAddress, true, mCallback)); } } } Loading services/core/java/com/android/server/hdmi/DeviceSelectAction.java +3 −2 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.hardware.hdmi.IHdmiControlCallback; import android.os.RemoteException; import android.util.Slog; import com.android.server.hdmi.HdmiCecLocalDevice.ActiveSource; import com.android.server.hdmi.HdmiControlService.SendMessageCallback; /** Loading Loading @@ -130,10 +131,10 @@ final class DeviceSelectAction extends FeatureAction { return false; case STATE_WAIT_FOR_ACTIVE_SOURCE: if (opcode == Constants.MESSAGE_ACTIVE_SOURCE) { int activePath = HdmiUtils.twoBytesToInt(params); int physicalAddress = HdmiUtils.twoBytesToInt(params); ActiveSourceHandler .create((HdmiCecLocalDeviceTv) localDevice(), mCallback) .process(cmd.getSource(), activePath); .process(ActiveSource.of(cmd.getSource(), physicalAddress)); finish(); return true; } Loading services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +45 −11 Original line number Diff line number Diff line Loading @@ -49,9 +49,41 @@ abstract class HdmiCecLocalDevice { protected int mPreferredAddress; protected HdmiCecDeviceInfo mDeviceInfo; static class ActiveSource { int logicalAddress; int physicalAddress; public ActiveSource(int logical, int physical) { logicalAddress = logical; physicalAddress = physical; } public static ActiveSource of(int logical, int physical) { return new ActiveSource(logical, physical); } public boolean isValid() { return HdmiUtils.isValidAddress(logicalAddress); } public boolean equals(int logical, int physical) { return logicalAddress == logical && physicalAddress == physical; } @Override public boolean equals(Object obj) { if (obj instanceof ActiveSource) { ActiveSource that = (ActiveSource) obj; return that.logicalAddress == logicalAddress && that.physicalAddress == physicalAddress; } return false; } @Override public int hashCode() { return logicalAddress * 29 + physicalAddress; } } // Logical address of the active source. @GuardedBy("mLock") private int mActiveSource; protected final ActiveSource mActiveSource = new ActiveSource(-1, Constants.INVALID_PHYSICAL_ADDRESS); // Active routing path. Physical address of the active source but not all the time, such as // when the new active source does not claim itself to be one. Note that we don't keep Loading Loading @@ -549,15 +581,24 @@ abstract class HdmiCecLocalDevice { return mService.isConnectedToArcPort(path); } int getActiveSource() { ActiveSource getActiveSource() { synchronized (mLock) { return mActiveSource; } } void setActiveSource(int source) { void setActiveSource(ActiveSource newActive) { setActiveSource(newActive.logicalAddress, newActive.physicalAddress); } void setActiveSource(HdmiCecDeviceInfo info) { setActiveSource(info.getLogicalAddress(), info.getPhysicalAddress()); } void setActiveSource(int logicalAddress, int physicalAddress) { synchronized (mLock) { mActiveSource = source; mActiveSource.logicalAddress = logicalAddress; mActiveSource.physicalAddress = physicalAddress; } } Loading Loading @@ -596,13 +637,6 @@ abstract class HdmiCecLocalDevice { } } void updateActiveDevice(int logicalAddress, int physicalAddress) { synchronized (mLock) { mActiveSource = logicalAddress; mActiveRoutingPath = physicalAddress; } } @ServiceThreadOnly HdmiCecMessageCache getCecMessageCache() { assertRunOnServiceThread(); Loading services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +56 −36 Original line number Diff line number Diff line Loading @@ -147,12 +147,15 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { if (targetAddress == Constants.ADDR_INTERNAL) { handleSelectInternalSource(); // Switching to internal source is always successful even when CEC control is disabled. setActiveSource(targetAddress); setActiveSource(targetAddress, mService.getPhysicalAddress()); invokeCallback(callback, HdmiControlManager.RESULT_SUCCESS); return; } if (!mService.isControlEnabled()) { setActiveSource(targetAddress); HdmiCecDeviceInfo info = getDeviceInfo(targetAddress); if (info != null) { setActiveSource(info); } invokeCallback(callback, HdmiControlManager.RESULT_INCORRECT_MODE); return; } Loading @@ -169,7 +172,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { private void handleSelectInternalSource() { assertRunOnServiceThread(); // Seq #18 if (mService.isControlEnabled() && getActiveSource() != mAddress) { if (mService.isControlEnabled() && mActiveSource.logicalAddress != mAddress) { updateActiveSource(mAddress, mService.getPhysicalAddress()); // TODO: Check if this comes from <Text/Image View On> - if true, do nothing. HdmiCecMessage activeSource = HdmiCecMessageBuilder.buildActiveSource( Loading @@ -179,16 +182,22 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { } @ServiceThreadOnly void updateActiveSource(int activeSource, int activePath) { void updateActiveSource(int logicalAddress, int physicalAddress) { assertRunOnServiceThread(); updateActiveSource(ActiveSource.of(logicalAddress, physicalAddress)); } @ServiceThreadOnly void updateActiveSource(ActiveSource newActive) { assertRunOnServiceThread(); // Seq #14 if (activeSource == getActiveSource() && activePath == getActivePath()) { if (mActiveSource.equals(newActive)) { return; } setActiveSource(activeSource); setActivePath(activePath); if (getDeviceInfo(activeSource) != null && activeSource != mAddress) { if (mService.pathToPortId(activePath) == getActivePortId()) { setActiveSource(newActive); int logicalAddress = newActive.logicalAddress; if (getDeviceInfo(logicalAddress) != null && logicalAddress != mAddress) { if (mService.pathToPortId(newActive.physicalAddress) == getActivePortId()) { setPrevPortId(getActivePortId()); } // TODO: Show the OSD banner related to the new active source device. Loading Loading @@ -222,16 +231,26 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { } @ServiceThreadOnly void updateActivePortId(int portId) { void updateActiveInput(int path, boolean notifyInputChange) { assertRunOnServiceThread(); // Seq #15 int portId = mService.pathToPortId(path); if (portId == getActivePortId()) { return; } setActivePath(path); setPrevPortId(portId); // TODO: Actually switch the physical port here. Handle PAP/PIP as well. // TODO: Handle PAP/PIP case. // Show OSD port change banner mService.invokeInputChangeListener(getActiveSource()); if (notifyInputChange) { ActiveSource activeSource = getActiveSource(); HdmiCecDeviceInfo info = getDeviceInfo(activeSource.logicalAddress); if (info == null) { info = new HdmiCecDeviceInfo(Constants.ADDR_INVALID, path, portId, HdmiCecDeviceInfo.DEVICE_RESERVED, 0, null); } mService.invokeInputChangeListener(info); } } @ServiceThreadOnly Loading @@ -242,26 +261,25 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { invokeCallback(callback, HdmiControlManager.RESULT_INCORRECT_MODE); return; } if (!mService.isControlEnabled()) { setActivePortId(portId); invokeCallback(callback, HdmiControlManager.RESULT_INCORRECT_MODE); return; } if (portId == getActivePortId()) { invokeCallback(callback, HdmiControlManager.RESULT_SUCCESS); return; } setActiveSource(Constants.ADDR_INVALID, Constants.INVALID_PHYSICAL_ADDRESS); if (!mService.isControlEnabled()) { setActivePortId(portId); invokeCallback(callback, HdmiControlManager.RESULT_INCORRECT_MODE); return; } // TODO: Return immediately if the operation is triggered by <Text/Image View On> // and this is the first notification about the active input after power-on // (switch to HDMI didn't happen so far but is expected to happen soon). removeAction(RoutingControlAction.class); int oldPath = mService.portIdToPath(mService.portIdToPath(getActivePortId())); int oldPath = mService.portIdToPath(getActivePortId()); int newPath = mService.portIdToPath(portId); HdmiCecMessage routingChange = HdmiCecMessageBuilder.buildRoutingChange(mAddress, oldPath, newPath); mService.sendCecCommand(routingChange); removeAction(RoutingControlAction.class); addAndStartAction(new RoutingControlAction(this, newPath, false, callback)); } Loading @@ -284,7 +302,8 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { action.get(0).processKeyEvent(keyCode, isPressed); } else { if (isPressed) { addAndStartAction(new SendKeyAction(this, getActiveSource(), keyCode)); int logicalAddress = getActiveSource().logicalAddress; addAndStartAction(new SendKeyAction(this, logicalAddress, keyCode)); } else { Slog.w(TAG, "Discard key release event"); } Loading @@ -306,12 +325,13 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { @ServiceThreadOnly protected boolean handleActiveSource(HdmiCecMessage message) { assertRunOnServiceThread(); int address = message.getSource(); int path = HdmiUtils.twoBytesToInt(message.getParams()); if (getDeviceInfo(address) == null) { handleNewDeviceAtTheTailOfActivePath(path); int logicalAddress = message.getSource(); int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams()); if (getDeviceInfo(logicalAddress) == null) { handleNewDeviceAtTheTailOfActivePath(physicalAddress); } else { ActiveSourceHandler.create(this, null).process(address, path); ActiveSource activeSource = ActiveSource.of(logicalAddress, physicalAddress); ActiveSourceHandler.create(this, null).process(activeSource); } return true; } Loading @@ -323,7 +343,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { // Seq #10 // Ignore <Inactive Source> from non-active source device. if (getActiveSource() != message.getSource()) { if (getActiveSource().logicalAddress != message.getSource()) { return true; } if (isProhibitMode()) { Loading @@ -342,7 +362,6 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { } // TODO: Switch the TV freeze mode off setActivePortId(portId); doManualPortSwitching(portId, null); setPrevPortId(Constants.INVALID_PORT_ID); } Loading @@ -354,7 +373,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { protected boolean handleRequestActiveSource(HdmiCecMessage message) { assertRunOnServiceThread(); // Seq #19 if (mAddress == getActiveSource()) { if (mAddress == getActiveSource().logicalAddress) { mService.sendCecCommand( HdmiCecMessageBuilder.buildActiveSource(mAddress, getActivePath())); } Loading Loading @@ -392,11 +411,11 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { if (!isInDeviceList(path, address)) { handleNewDeviceAtTheTailOfActivePath(path); } startNewDeviceAction(address, path); startNewDeviceAction(ActiveSource.of(address, path)); return true; } void startNewDeviceAction(int address, int path) { void startNewDeviceAction(ActiveSource activeSource) { for (NewDeviceAction action : getActions(NewDeviceAction.class)) { // If there is new device action which has the same logical address and path // ignore new request. Loading @@ -406,12 +425,13 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { // in. However, TV can detect a new device from HotPlugDetectionAction, // which sends <Give Physical Address> to the source for newly detected // device. if (action.isActionOf(address, path)) { if (action.isActionOf(activeSource)) { return; } } addAndStartAction(new NewDeviceAction(this, address, path)); addAndStartAction(new NewDeviceAction(this, activeSource.logicalAddress, activeSource.physicalAddress)); } private void handleNewDeviceAtTheTailOfActivePath(int path) { Loading services/core/java/com/android/server/hdmi/HdmiControlService.java +10 −3 Original line number Diff line number Diff line Loading @@ -724,6 +724,10 @@ public final class HdmiControlService extends SystemService { runOnServiceThread(new Runnable() { @Override public void run() { if (callback == null) { Slog.e(TAG, "Callback cannot be null"); return; } HdmiCecLocalDeviceTv tv = tv(); if (tv == null) { Slog.w(TAG, "Local tv device not available"); Loading @@ -741,6 +745,10 @@ public final class HdmiControlService extends SystemService { runOnServiceThread(new Runnable() { @Override public void run() { if (callback == null) { Slog.e(TAG, "Callback cannot be null"); return; } HdmiCecLocalDeviceTv tv = tv(); if (tv == null) { Slog.w(TAG, "Local tv device not available"); Loading Loading @@ -1218,12 +1226,11 @@ public final class HdmiControlService extends SystemService { } } void invokeInputChangeListener(int activeAddress) { void invokeInputChangeListener(HdmiCecDeviceInfo info) { synchronized (mLock) { if (mInputChangeListener != null) { HdmiCecDeviceInfo activeSource = getDeviceInfo(activeAddress); try { mInputChangeListener.onChanged(activeSource); mInputChangeListener.onChanged(info); } catch (RemoteException e) { Slog.w(TAG, "Exception thrown by IHdmiInputChangeListener: " + e); } Loading Loading
services/core/java/com/android/server/hdmi/ActiveSourceHandler.java +21 −18 Original line number Diff line number Diff line Loading @@ -23,6 +23,8 @@ import android.hardware.hdmi.HdmiControlManager; import android.os.RemoteException; import android.util.Slog; import com.android.server.hdmi.HdmiCecLocalDevice.ActiveSource; /** * Handles CEC command <Active Source>. * <p> Loading Loading @@ -54,44 +56,45 @@ final class ActiveSourceHandler { /** * Handles the incoming active source command. * * @param activeAddress logical address of the device to be the active source * @param activePath routing path of the device to be the active source * @param newActive new active source information */ void process(int activeAddress, int activePath) { void process(ActiveSource newActive) { // Seq #17 HdmiCecLocalDeviceTv tv = mSource; if (getSourcePath() == activePath && tv.getActiveSource() == getSourceAddress()) { ActiveSource activeSource = tv.getActiveSource(); if (activeSource.equals(newActive)) { invokeCallback(HdmiControlManager.RESULT_SUCCESS); return; } HdmiCecDeviceInfo device = mService.getDeviceInfo(activeAddress); HdmiCecDeviceInfo device = mService.getDeviceInfo(newActive.logicalAddress); if (device == null) { tv.startNewDeviceAction(activeAddress, activePath); tv.startNewDeviceAction(newActive); } int currentActive = tv.getActiveSource(); int currentPath = tv.getActivePath(); ActiveSource current = tv.getActiveSource(); if (!tv.isProhibitMode()) { tv.updateActiveSource(activeAddress, activePath); if (currentActive != activeAddress && currentPath != activePath) { tv.updateActivePortId(mService.pathToPortId(activePath)); tv.updateActiveSource(newActive); if (!current.equals(newActive)) { boolean notifyInputChange = (mCallback == null); tv.updateActiveInput(newActive.physicalAddress, notifyInputChange); } invokeCallback(HdmiControlManager.RESULT_SUCCESS); } else { // TV is in a mode that should keep its current source/input from // being changed for its operation. Reclaim the active source // or switch the port back to the one used for the current mode. if (currentActive == getSourceAddress()) { HdmiCecMessage activeSource = HdmiCecMessageBuilder.buildActiveSource(currentActive, currentPath); mService.sendCecCommand(activeSource); tv.updateActiveSource(currentActive, currentPath); if (current.logicalAddress == getSourceAddress()) { HdmiCecMessage activeSourceCommand = HdmiCecMessageBuilder.buildActiveSource( current.logicalAddress, current.physicalAddress); mService.sendCecCommand(activeSourceCommand); tv.updateActiveSource(current); invokeCallback(HdmiControlManager.RESULT_SUCCESS); } else { HdmiCecMessage routingChange = HdmiCecMessageBuilder.buildRoutingChange( getSourceAddress(), activePath, currentPath); getSourceAddress(), newActive.physicalAddress, current.physicalAddress); mService.sendCecCommand(routingChange); tv.addAndStartAction(new RoutingControlAction(tv, currentPath, true, mCallback)); tv.addAndStartAction( new RoutingControlAction(tv, current.physicalAddress, true, mCallback)); } } } Loading
services/core/java/com/android/server/hdmi/DeviceSelectAction.java +3 −2 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.hardware.hdmi.IHdmiControlCallback; import android.os.RemoteException; import android.util.Slog; import com.android.server.hdmi.HdmiCecLocalDevice.ActiveSource; import com.android.server.hdmi.HdmiControlService.SendMessageCallback; /** Loading Loading @@ -130,10 +131,10 @@ final class DeviceSelectAction extends FeatureAction { return false; case STATE_WAIT_FOR_ACTIVE_SOURCE: if (opcode == Constants.MESSAGE_ACTIVE_SOURCE) { int activePath = HdmiUtils.twoBytesToInt(params); int physicalAddress = HdmiUtils.twoBytesToInt(params); ActiveSourceHandler .create((HdmiCecLocalDeviceTv) localDevice(), mCallback) .process(cmd.getSource(), activePath); .process(ActiveSource.of(cmd.getSource(), physicalAddress)); finish(); return true; } Loading
services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +45 −11 Original line number Diff line number Diff line Loading @@ -49,9 +49,41 @@ abstract class HdmiCecLocalDevice { protected int mPreferredAddress; protected HdmiCecDeviceInfo mDeviceInfo; static class ActiveSource { int logicalAddress; int physicalAddress; public ActiveSource(int logical, int physical) { logicalAddress = logical; physicalAddress = physical; } public static ActiveSource of(int logical, int physical) { return new ActiveSource(logical, physical); } public boolean isValid() { return HdmiUtils.isValidAddress(logicalAddress); } public boolean equals(int logical, int physical) { return logicalAddress == logical && physicalAddress == physical; } @Override public boolean equals(Object obj) { if (obj instanceof ActiveSource) { ActiveSource that = (ActiveSource) obj; return that.logicalAddress == logicalAddress && that.physicalAddress == physicalAddress; } return false; } @Override public int hashCode() { return logicalAddress * 29 + physicalAddress; } } // Logical address of the active source. @GuardedBy("mLock") private int mActiveSource; protected final ActiveSource mActiveSource = new ActiveSource(-1, Constants.INVALID_PHYSICAL_ADDRESS); // Active routing path. Physical address of the active source but not all the time, such as // when the new active source does not claim itself to be one. Note that we don't keep Loading Loading @@ -549,15 +581,24 @@ abstract class HdmiCecLocalDevice { return mService.isConnectedToArcPort(path); } int getActiveSource() { ActiveSource getActiveSource() { synchronized (mLock) { return mActiveSource; } } void setActiveSource(int source) { void setActiveSource(ActiveSource newActive) { setActiveSource(newActive.logicalAddress, newActive.physicalAddress); } void setActiveSource(HdmiCecDeviceInfo info) { setActiveSource(info.getLogicalAddress(), info.getPhysicalAddress()); } void setActiveSource(int logicalAddress, int physicalAddress) { synchronized (mLock) { mActiveSource = source; mActiveSource.logicalAddress = logicalAddress; mActiveSource.physicalAddress = physicalAddress; } } Loading Loading @@ -596,13 +637,6 @@ abstract class HdmiCecLocalDevice { } } void updateActiveDevice(int logicalAddress, int physicalAddress) { synchronized (mLock) { mActiveSource = logicalAddress; mActiveRoutingPath = physicalAddress; } } @ServiceThreadOnly HdmiCecMessageCache getCecMessageCache() { assertRunOnServiceThread(); Loading
services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +56 −36 Original line number Diff line number Diff line Loading @@ -147,12 +147,15 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { if (targetAddress == Constants.ADDR_INTERNAL) { handleSelectInternalSource(); // Switching to internal source is always successful even when CEC control is disabled. setActiveSource(targetAddress); setActiveSource(targetAddress, mService.getPhysicalAddress()); invokeCallback(callback, HdmiControlManager.RESULT_SUCCESS); return; } if (!mService.isControlEnabled()) { setActiveSource(targetAddress); HdmiCecDeviceInfo info = getDeviceInfo(targetAddress); if (info != null) { setActiveSource(info); } invokeCallback(callback, HdmiControlManager.RESULT_INCORRECT_MODE); return; } Loading @@ -169,7 +172,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { private void handleSelectInternalSource() { assertRunOnServiceThread(); // Seq #18 if (mService.isControlEnabled() && getActiveSource() != mAddress) { if (mService.isControlEnabled() && mActiveSource.logicalAddress != mAddress) { updateActiveSource(mAddress, mService.getPhysicalAddress()); // TODO: Check if this comes from <Text/Image View On> - if true, do nothing. HdmiCecMessage activeSource = HdmiCecMessageBuilder.buildActiveSource( Loading @@ -179,16 +182,22 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { } @ServiceThreadOnly void updateActiveSource(int activeSource, int activePath) { void updateActiveSource(int logicalAddress, int physicalAddress) { assertRunOnServiceThread(); updateActiveSource(ActiveSource.of(logicalAddress, physicalAddress)); } @ServiceThreadOnly void updateActiveSource(ActiveSource newActive) { assertRunOnServiceThread(); // Seq #14 if (activeSource == getActiveSource() && activePath == getActivePath()) { if (mActiveSource.equals(newActive)) { return; } setActiveSource(activeSource); setActivePath(activePath); if (getDeviceInfo(activeSource) != null && activeSource != mAddress) { if (mService.pathToPortId(activePath) == getActivePortId()) { setActiveSource(newActive); int logicalAddress = newActive.logicalAddress; if (getDeviceInfo(logicalAddress) != null && logicalAddress != mAddress) { if (mService.pathToPortId(newActive.physicalAddress) == getActivePortId()) { setPrevPortId(getActivePortId()); } // TODO: Show the OSD banner related to the new active source device. Loading Loading @@ -222,16 +231,26 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { } @ServiceThreadOnly void updateActivePortId(int portId) { void updateActiveInput(int path, boolean notifyInputChange) { assertRunOnServiceThread(); // Seq #15 int portId = mService.pathToPortId(path); if (portId == getActivePortId()) { return; } setActivePath(path); setPrevPortId(portId); // TODO: Actually switch the physical port here. Handle PAP/PIP as well. // TODO: Handle PAP/PIP case. // Show OSD port change banner mService.invokeInputChangeListener(getActiveSource()); if (notifyInputChange) { ActiveSource activeSource = getActiveSource(); HdmiCecDeviceInfo info = getDeviceInfo(activeSource.logicalAddress); if (info == null) { info = new HdmiCecDeviceInfo(Constants.ADDR_INVALID, path, portId, HdmiCecDeviceInfo.DEVICE_RESERVED, 0, null); } mService.invokeInputChangeListener(info); } } @ServiceThreadOnly Loading @@ -242,26 +261,25 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { invokeCallback(callback, HdmiControlManager.RESULT_INCORRECT_MODE); return; } if (!mService.isControlEnabled()) { setActivePortId(portId); invokeCallback(callback, HdmiControlManager.RESULT_INCORRECT_MODE); return; } if (portId == getActivePortId()) { invokeCallback(callback, HdmiControlManager.RESULT_SUCCESS); return; } setActiveSource(Constants.ADDR_INVALID, Constants.INVALID_PHYSICAL_ADDRESS); if (!mService.isControlEnabled()) { setActivePortId(portId); invokeCallback(callback, HdmiControlManager.RESULT_INCORRECT_MODE); return; } // TODO: Return immediately if the operation is triggered by <Text/Image View On> // and this is the first notification about the active input after power-on // (switch to HDMI didn't happen so far but is expected to happen soon). removeAction(RoutingControlAction.class); int oldPath = mService.portIdToPath(mService.portIdToPath(getActivePortId())); int oldPath = mService.portIdToPath(getActivePortId()); int newPath = mService.portIdToPath(portId); HdmiCecMessage routingChange = HdmiCecMessageBuilder.buildRoutingChange(mAddress, oldPath, newPath); mService.sendCecCommand(routingChange); removeAction(RoutingControlAction.class); addAndStartAction(new RoutingControlAction(this, newPath, false, callback)); } Loading @@ -284,7 +302,8 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { action.get(0).processKeyEvent(keyCode, isPressed); } else { if (isPressed) { addAndStartAction(new SendKeyAction(this, getActiveSource(), keyCode)); int logicalAddress = getActiveSource().logicalAddress; addAndStartAction(new SendKeyAction(this, logicalAddress, keyCode)); } else { Slog.w(TAG, "Discard key release event"); } Loading @@ -306,12 +325,13 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { @ServiceThreadOnly protected boolean handleActiveSource(HdmiCecMessage message) { assertRunOnServiceThread(); int address = message.getSource(); int path = HdmiUtils.twoBytesToInt(message.getParams()); if (getDeviceInfo(address) == null) { handleNewDeviceAtTheTailOfActivePath(path); int logicalAddress = message.getSource(); int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams()); if (getDeviceInfo(logicalAddress) == null) { handleNewDeviceAtTheTailOfActivePath(physicalAddress); } else { ActiveSourceHandler.create(this, null).process(address, path); ActiveSource activeSource = ActiveSource.of(logicalAddress, physicalAddress); ActiveSourceHandler.create(this, null).process(activeSource); } return true; } Loading @@ -323,7 +343,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { // Seq #10 // Ignore <Inactive Source> from non-active source device. if (getActiveSource() != message.getSource()) { if (getActiveSource().logicalAddress != message.getSource()) { return true; } if (isProhibitMode()) { Loading @@ -342,7 +362,6 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { } // TODO: Switch the TV freeze mode off setActivePortId(portId); doManualPortSwitching(portId, null); setPrevPortId(Constants.INVALID_PORT_ID); } Loading @@ -354,7 +373,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { protected boolean handleRequestActiveSource(HdmiCecMessage message) { assertRunOnServiceThread(); // Seq #19 if (mAddress == getActiveSource()) { if (mAddress == getActiveSource().logicalAddress) { mService.sendCecCommand( HdmiCecMessageBuilder.buildActiveSource(mAddress, getActivePath())); } Loading Loading @@ -392,11 +411,11 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { if (!isInDeviceList(path, address)) { handleNewDeviceAtTheTailOfActivePath(path); } startNewDeviceAction(address, path); startNewDeviceAction(ActiveSource.of(address, path)); return true; } void startNewDeviceAction(int address, int path) { void startNewDeviceAction(ActiveSource activeSource) { for (NewDeviceAction action : getActions(NewDeviceAction.class)) { // If there is new device action which has the same logical address and path // ignore new request. Loading @@ -406,12 +425,13 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { // in. However, TV can detect a new device from HotPlugDetectionAction, // which sends <Give Physical Address> to the source for newly detected // device. if (action.isActionOf(address, path)) { if (action.isActionOf(activeSource)) { return; } } addAndStartAction(new NewDeviceAction(this, address, path)); addAndStartAction(new NewDeviceAction(this, activeSource.logicalAddress, activeSource.physicalAddress)); } private void handleNewDeviceAtTheTailOfActivePath(int path) { Loading
services/core/java/com/android/server/hdmi/HdmiControlService.java +10 −3 Original line number Diff line number Diff line Loading @@ -724,6 +724,10 @@ public final class HdmiControlService extends SystemService { runOnServiceThread(new Runnable() { @Override public void run() { if (callback == null) { Slog.e(TAG, "Callback cannot be null"); return; } HdmiCecLocalDeviceTv tv = tv(); if (tv == null) { Slog.w(TAG, "Local tv device not available"); Loading @@ -741,6 +745,10 @@ public final class HdmiControlService extends SystemService { runOnServiceThread(new Runnable() { @Override public void run() { if (callback == null) { Slog.e(TAG, "Callback cannot be null"); return; } HdmiCecLocalDeviceTv tv = tv(); if (tv == null) { Slog.w(TAG, "Local tv device not available"); Loading Loading @@ -1218,12 +1226,11 @@ public final class HdmiControlService extends SystemService { } } void invokeInputChangeListener(int activeAddress) { void invokeInputChangeListener(HdmiCecDeviceInfo info) { synchronized (mLock) { if (mInputChangeListener != null) { HdmiCecDeviceInfo activeSource = getDeviceInfo(activeAddress); try { mInputChangeListener.onChanged(activeSource); mInputChangeListener.onChanged(info); } catch (RemoteException e) { Slog.w(TAG, "Exception thrown by IHdmiInputChangeListener: " + e); } Loading