Loading services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java +2 −1 Original line number Diff line number Diff line Loading @@ -339,7 +339,8 @@ final class DeviceDiscoveryAction extends HdmiCecFeatureAction { // This is to manager CEC device separately in case they don't have address. if (mIsTvDevice) { tv().updateCecSwitchInfo(current.mLogicalAddress, current.mDeviceType, localDevice().mService.getHdmiCecNetwork().updateCecSwitchInfo(current.mLogicalAddress, current.mDeviceType, current.mPhysicalAddress); } increaseProcessedDeviceCount(); Loading services/core/java/com/android/server/hdmi/HdmiCecController.java +4 −71 Original line number Diff line number Diff line Loading @@ -32,7 +32,6 @@ import android.os.Looper; import android.os.RemoteException; import android.stats.hdmi.HdmiStatsEnums; import android.util.Slog; import android.util.SparseArray; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.IndentingPrintWriter; Loading Loading @@ -97,7 +96,7 @@ final class HdmiCecController { private final Predicate<Integer> mRemoteDeviceAddressPredicate = new Predicate<Integer>() { @Override public boolean test(Integer address) { return !isAllocatedLocalDeviceAddress(address); return !mService.getHdmiCecNetwork().isAllocatedLocalDeviceAddress(address); } }; Loading @@ -118,9 +117,6 @@ final class HdmiCecController { private final HdmiControlService mService; // Stores the local CEC devices in the system. Device type is used for key. private final SparseArray<HdmiCecLocalDevice> mLocalDevices = new SparseArray<>(); // Stores recent CEC messages and HDMI Hotplug event history for debugging purpose. private final ArrayBlockingQueue<Dumpable> mMessageHistory = new ArrayBlockingQueue<>(MAX_HDMI_MESSAGE_HISTORY); Loading Loading @@ -173,12 +169,6 @@ final class HdmiCecController { nativeWrapper.setCallback(new HdmiCecCallback()); } @ServiceThreadOnly void addLocalDevice(int deviceType, HdmiCecLocalDevice device) { assertRunOnServiceThread(); mLocalDevices.put(deviceType, device); } /** * Allocate a new logical address of the given device type. Allocated * address will be reported through {@link AllocateAddressCallback}. Loading Loading @@ -268,17 +258,6 @@ final class HdmiCecController { return mNativeWrapperImpl.nativeGetPortInfos(); } /** * Return the locally hosted logical device of a given type. * * @param deviceType logical device type * @return {@link HdmiCecLocalDevice} instance if the instance of the type is available; * otherwise null. */ HdmiCecLocalDevice getLocalDevice(int deviceType) { return mLocalDevices.get(deviceType); } /** * Add a new logical address to the device. Device's HW should be notified * when a new logical address is assigned to a device, so that it can accept Loading Loading @@ -307,18 +286,9 @@ final class HdmiCecController { @ServiceThreadOnly void clearLogicalAddress() { assertRunOnServiceThread(); for (int i = 0; i < mLocalDevices.size(); ++i) { mLocalDevices.valueAt(i).clearAddress(); } mNativeWrapperImpl.nativeClearLogicalAddress(); } @ServiceThreadOnly void clearLocalDevices() { assertRunOnServiceThread(); mLocalDevices.clear(); } /** * Return the physical address of the device. * Loading Loading @@ -428,17 +398,6 @@ final class HdmiCecController { runDevicePolling(sourceAddress, pollingCandidates, retryCount, callback, allocated); } /** * Return a list of all {@link HdmiCecLocalDevice}s. * * <p>Declared as package-private. accessed by {@link HdmiControlService} only. */ @ServiceThreadOnly List<HdmiCecLocalDevice> getLocalDeviceList() { assertRunOnServiceThread(); return HdmiUtils.sparseArrayToList(mLocalDevices); } private List<Integer> pickPollCandidates(int pickStrategy) { int strategy = pickStrategy & Constants.POLL_STRATEGY_MASK; Predicate<Integer> pickPredicate = null; Loading Loading @@ -474,17 +433,6 @@ final class HdmiCecController { return pollingCandidates; } @ServiceThreadOnly private boolean isAllocatedLocalDeviceAddress(int address) { assertRunOnServiceThread(); for (int i = 0; i < mLocalDevices.size(); ++i) { if (mLocalDevices.valueAt(i).isAddressOf(address)) { return true; } } return false; } @ServiceThreadOnly private void runDevicePolling(final int sourceAddress, final List<Integer> candidates, final int retryCount, Loading Loading @@ -578,7 +526,7 @@ final class HdmiCecController { if (address == Constants.ADDR_BROADCAST) { return true; } return isAllocatedLocalDeviceAddress(address); return mService.getHdmiCecNetwork().isAllocatedLocalDeviceAddress(address); } @ServiceThreadOnly Loading Loading @@ -682,7 +630,7 @@ final class HdmiCecController { private int incomingMessageDirection(int srcAddress, int dstAddress) { boolean sourceIsLocal = false; boolean destinationIsLocal = false; for (HdmiCecLocalDevice localDevice : getLocalDeviceList()) { for (HdmiCecLocalDevice localDevice : mService.getHdmiCecNetwork().getLocalDeviceList()) { int logicalAddress = localDevice.getDeviceInfo().getLogicalAddress(); if (logicalAddress == srcAddress) { sourceIsLocal = true; Loading Loading @@ -731,24 +679,9 @@ final class HdmiCecController { } void dump(final IndentingPrintWriter pw) { final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); for (int i = 0; i < mLocalDevices.size(); ++i) { pw.println("HdmiCecLocalDevice #" + mLocalDevices.keyAt(i) + ":"); pw.increaseIndent(); mLocalDevices.valueAt(i).dump(pw); pw.println("Active Source history:"); pw.increaseIndent(); for (Dumpable activeSourceEvent : mLocalDevices.valueAt(i).getActiveSourceHistory()) { activeSourceEvent.dump(pw, sdf); } pw.decreaseIndent(); pw.decreaseIndent(); } pw.println("CEC message history:"); pw.increaseIndent(); final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); for (Dumpable record : mMessageHistory) { record.dump(pw, sdf); } Loading services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +24 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.hdmi; import android.annotation.CallSuper; import android.annotation.Nullable; import android.hardware.hdmi.HdmiDeviceInfo; import android.hardware.hdmi.IHdmiControlCallback; Loading Loading @@ -471,8 +472,27 @@ abstract class HdmiCecLocalDevice { return false; } @CallSuper protected boolean handleReportPhysicalAddress(HdmiCecMessage message) { return false; // <Report Physical Address> is also handled in HdmiCecNetwork to update the local network // state int address = message.getSource(); // Ignore if [Device Discovery Action] is going on. if (hasAction(DeviceDiscoveryAction.class)) { Slog.i(TAG, "Ignored while Device Discovery Action is in progress: " + message); return true; } HdmiDeviceInfo cecDeviceInfo = mService.getHdmiCecNetwork().getCecDeviceInfo(address); // If no non-default display name is available for the device, request the devices OSD name. if (cecDeviceInfo.getDisplayName().equals(HdmiUtils.getDefaultDeviceName(address))) { mService.sendCecCommand( HdmiCecMessageBuilder.buildGiveOsdNameCommand(mAddress, address)); } return true; } protected boolean handleSystemAudioModeStatus(HdmiCecMessage message) { Loading Loading @@ -708,7 +728,7 @@ abstract class HdmiCecLocalDevice { } protected boolean handleSetOsdName(HdmiCecMessage message) { // The default behavior of <Set Osd Name> is doing nothing. // <Set OSD name> is also handled in HdmiCecNetwork to update the local network state return true; } Loading @@ -724,7 +744,8 @@ abstract class HdmiCecLocalDevice { } protected boolean handleReportPowerStatus(HdmiCecMessage message) { return false; // <Report Power Status> is also handled in HdmiCecNetwork to update the local network state return true; } protected boolean handleTimerStatus(HdmiCecMessage message) { Loading services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java +7 −259 Original line number Diff line number Diff line Loading @@ -37,7 +37,6 @@ import android.os.SystemProperties; import android.provider.Settings.Global; import android.sysprop.HdmiProperties; import android.util.Slog; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; Loading @@ -54,15 +53,12 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.stream.Collectors; /** * Represent a logical device of type {@link HdmiDeviceInfo#DEVICE_AUDIO_SYSTEM} residing in Android * system. Loading Loading @@ -104,14 +100,6 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { @GuardedBy("mLock") private final HashMap<String, HdmiDeviceInfo> mTvInputsToDeviceInfo = new HashMap<>(); // Copy of mDeviceInfos to guarantee thread-safety. @GuardedBy("mLock") private List<HdmiDeviceInfo> mSafeAllDeviceInfos = Collections.emptyList(); // Map-like container of all cec devices. // device id is used as key of container. private final SparseArray<HdmiDeviceInfo> mDeviceInfos = new SparseArray<>(); // Message buffer used to buffer selected messages to process later. <Active Source> // from a source device, for instance, needs to be buffered if the device is not // discovered yet. The buffered commands are taken out and when they are ready to Loading Loading @@ -187,135 +175,6 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { return info != null; } /** * Called when a device is newly added or a new device is detected or * an existing device is updated. * * @param info device info of a new device. */ @ServiceThreadOnly final void addCecDevice(HdmiDeviceInfo info) { assertRunOnServiceThread(); HdmiDeviceInfo old = addDeviceInfo(info); if (info.getPhysicalAddress() == mService.getPhysicalAddress()) { // The addition of the device itself should not be notified. // Note that different logical address could still be the same local device. return; } if (old == null) { invokeDeviceEventListener(info, HdmiControlManager.DEVICE_EVENT_ADD_DEVICE); } else if (!old.equals(info)) { invokeDeviceEventListener(old, HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE); invokeDeviceEventListener(info, HdmiControlManager.DEVICE_EVENT_ADD_DEVICE); } } /** * Called when a device is removed or removal of device is detected. * * @param address a logical address of a device to be removed */ @ServiceThreadOnly final void removeCecDevice(int address) { assertRunOnServiceThread(); HdmiDeviceInfo info = removeDeviceInfo(HdmiDeviceInfo.idForCecDevice(address)); mCecMessageCache.flushMessagesFrom(address); invokeDeviceEventListener(info, HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE); } /** * Called when a device is updated. * * @param info device info of the updating device. */ @ServiceThreadOnly final void updateCecDevice(HdmiDeviceInfo info) { assertRunOnServiceThread(); HdmiDeviceInfo old = addDeviceInfo(info); if (old == null) { invokeDeviceEventListener(info, HdmiControlManager.DEVICE_EVENT_ADD_DEVICE); } else if (!old.equals(info)) { invokeDeviceEventListener(info, HdmiControlManager.DEVICE_EVENT_UPDATE_DEVICE); } } /** * Add a new {@link HdmiDeviceInfo}. It returns old device info which has the same * logical address as new device info's. * * @param deviceInfo a new {@link HdmiDeviceInfo} to be added. * @return {@code null} if it is new device. Otherwise, returns old {@HdmiDeviceInfo} * that has the same logical address as new one has. */ @ServiceThreadOnly @VisibleForTesting protected HdmiDeviceInfo addDeviceInfo(HdmiDeviceInfo deviceInfo) { assertRunOnServiceThread(); mService.checkLogicalAddressConflictAndReallocate(deviceInfo.getLogicalAddress()); HdmiDeviceInfo oldDeviceInfo = getCecDeviceInfo(deviceInfo.getLogicalAddress()); if (oldDeviceInfo != null) { removeDeviceInfo(deviceInfo.getId()); } mDeviceInfos.append(deviceInfo.getId(), deviceInfo); updateSafeDeviceInfoList(); return oldDeviceInfo; } /** * Remove a device info corresponding to the given {@code logicalAddress}. * It returns removed {@link HdmiDeviceInfo} if exists. * * @param id id of device to be removed * @return removed {@link HdmiDeviceInfo} it exists. Otherwise, returns {@code null} */ @ServiceThreadOnly private HdmiDeviceInfo removeDeviceInfo(int id) { assertRunOnServiceThread(); HdmiDeviceInfo deviceInfo = mDeviceInfos.get(id); if (deviceInfo != null) { mDeviceInfos.remove(id); } updateSafeDeviceInfoList(); return deviceInfo; } /** * Return a {@link HdmiDeviceInfo} corresponding to the given {@code logicalAddress}. * * @param logicalAddress logical address of the device to be retrieved * @return {@link HdmiDeviceInfo} matched with the given {@code logicalAddress}. * Returns null if no logical address matched */ @ServiceThreadOnly HdmiDeviceInfo getCecDeviceInfo(int logicalAddress) { assertRunOnServiceThread(); return mDeviceInfos.get(HdmiDeviceInfo.idForCecDevice(logicalAddress)); } @ServiceThreadOnly private void updateSafeDeviceInfoList() { assertRunOnServiceThread(); List<HdmiDeviceInfo> copiedDevices = HdmiUtils.sparseArrayToList(mDeviceInfos); synchronized (mLock) { mSafeAllDeviceInfos = copiedDevices; } } @GuardedBy("mLock") List<HdmiDeviceInfo> getSafeCecDevicesLocked() { ArrayList<HdmiDeviceInfo> infoList = new ArrayList<>(); for (HdmiDeviceInfo info : mSafeAllDeviceInfos) { infoList.add(info); } return infoList; } private void invokeDeviceEventListener(HdmiDeviceInfo info, int status) { mService.invokeDeviceEventListeners(info, status); } @Override @ServiceThreadOnly void onHotplug(int portId, boolean connected) { Loading @@ -342,7 +201,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { } // Update with TIF on the device removal. TIF callback will update // mPortIdToTvInputs and mPortIdToTvInputs. removeCecDevice(info.getLogicalAddress()); mService.getHdmiCecNetwork().removeCecDevice(this, info.getLogicalAddress()); } } Loading Loading @@ -399,7 +258,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { boolean lastSystemAudioControlStatus = SystemProperties.getBoolean(Constants.PROPERTY_LAST_SYSTEM_AUDIO_CONTROL, true); systemAudioControlOnPowerOn(systemAudioControlOnPowerOnProp, lastSystemAudioControlStatus); clearDeviceInfoList(); mService.getHdmiCecNetwork().clearDeviceList(); launchDeviceDiscovery(); startQueuedActions(); } Loading Loading @@ -458,7 +317,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { // If the new Active Source is under the current device, check if the device info and the TV // input is ready to switch to the new Active Source. If not ready, buffer the cec command // to handle later when the device is ready. HdmiDeviceInfo info = getCecDeviceInfo(logicalAddress); HdmiDeviceInfo info = mService.getHdmiCecNetwork().getCecDeviceInfo(logicalAddress); if (info == null) { HdmiLogger.debug("Device info %X not found; buffering the command", logicalAddress); mDelayedMessageBuffer.add(message); Loading @@ -472,79 +331,6 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { return true; } @Override @ServiceThreadOnly protected boolean handleReportPhysicalAddress(HdmiCecMessage message) { assertRunOnServiceThread(); int path = HdmiUtils.twoBytesToInt(message.getParams()); int address = message.getSource(); int type = message.getParams()[2]; // Ignore if [Device Discovery Action] is going on. if (hasAction(DeviceDiscoveryAction.class)) { Slog.i(TAG, "Ignored while Device Discovery Action is in progress: " + message); return true; } // Update the device info with TIF, note that the same device info could have added in // device discovery and we do not want to override it with default OSD name. Therefore we // need the following check to skip redundant device info updating. HdmiDeviceInfo oldDevice = getCecDeviceInfo(address); if (oldDevice == null || oldDevice.getPhysicalAddress() != path) { addCecDevice(new HdmiDeviceInfo( address, path, mService.pathToPortId(path), type, Constants.UNKNOWN_VENDOR_ID, "")); // if we are adding a new device info, send out a give osd name command // to update the name of the device in TIF mService.sendCecCommand( HdmiCecMessageBuilder.buildGiveOsdNameCommand(mAddress, address)); return true; } Slog.w(TAG, "Device info exists. Not updating on Physical Address."); return true; } @Override protected boolean handleReportPowerStatus(HdmiCecMessage command) { int newStatus = command.getParams()[0] & 0xFF; updateDevicePowerStatus(command.getSource(), newStatus); return true; } @Override @ServiceThreadOnly protected boolean handleSetOsdName(HdmiCecMessage message) { int source = message.getSource(); String osdName; HdmiDeviceInfo deviceInfo = getCecDeviceInfo(source); // If the device is not in device list, ignore it. if (deviceInfo == null) { Slog.i(TAG, "No source device info for <Set Osd Name>." + message); return true; } try { osdName = new String(message.getParams(), "US-ASCII"); } catch (UnsupportedEncodingException e) { Slog.e(TAG, "Invalid <Set Osd Name> request:" + message, e); return true; } if (deviceInfo.getDisplayName() != null && deviceInfo.getDisplayName().equals(osdName)) { Slog.d(TAG, "Ignore incoming <Set Osd Name> having same osd name:" + message); return true; } Slog.d(TAG, "Updating device OSD name from " + deviceInfo.getDisplayName() + " to " + osdName); updateCecDevice(new HdmiDeviceInfo(deviceInfo.getLogicalAddress(), deviceInfo.getPhysicalAddress(), deviceInfo.getPortId(), deviceInfo.getDeviceType(), deviceInfo.getVendorId(), osdName)); return true; } @Override @ServiceThreadOnly protected boolean handleInitiateArc(HdmiCecMessage message) { Loading Loading @@ -864,14 +650,9 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { != HdmiUtils.TARGET_NOT_UNDER_LOCAL_DEVICE) { return true; } boolean isDeviceInCecDeviceList = false; for (HdmiDeviceInfo info : HdmiUtils.sparseArrayToList(mDeviceInfos)) { if (info.getPhysicalAddress() == sourcePhysicalAddress) { isDeviceInCecDeviceList = true; break; } } if (!isDeviceInCecDeviceList) { HdmiDeviceInfo safeDeviceInfoByPath = mService.getHdmiCecNetwork().getSafeDeviceInfoByPath(sourcePhysicalAddress); if (safeDeviceInfoByPath == null) { switchInputOnReceivingNewActivePath(sourcePhysicalAddress); } } Loading Loading @@ -1345,24 +1126,6 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { routeToInputFromPortId(getRoutingPort()); } protected void updateDevicePowerStatus(int logicalAddress, int newPowerStatus) { HdmiDeviceInfo info = getCecDeviceInfo(logicalAddress); if (info == null) { Slog.w(TAG, "Can not update power status of non-existing device:" + logicalAddress); return; } if (info.getDevicePowerStatus() == newPowerStatus) { return; } HdmiDeviceInfo newInfo = HdmiUtils.cloneHdmiDeviceInfo(info, newPowerStatus); // addDeviceInfo replaces old device info with new one if exists. addDeviceInfo(newInfo); invokeDeviceEventListener(newInfo, HdmiControlManager.DEVICE_EVENT_UPDATE_DEVICE); } @ServiceThreadOnly private void launchDeviceDiscovery() { assertRunOnServiceThread(); Loading @@ -1375,27 +1138,13 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { @Override public void onDeviceDiscoveryDone(List<HdmiDeviceInfo> deviceInfos) { for (HdmiDeviceInfo info : deviceInfos) { addCecDevice(info); mService.getHdmiCecNetwork().addCecDevice(info); } } }); addAndStartAction(action); } // Clear all device info. @ServiceThreadOnly private void clearDeviceInfoList() { assertRunOnServiceThread(); for (HdmiDeviceInfo info : HdmiUtils.sparseArrayToList(mDeviceInfos)) { if (info.getPhysicalAddress() == mService.getPhysicalAddress()) { continue; } invokeDeviceEventListener(info, HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE); } mDeviceInfos.clear(); updateSafeDeviceInfoList(); } @Override protected void dump(IndentingPrintWriter pw) { pw.println("HdmiCecLocalDeviceAudioSystem:"); Loading @@ -1409,7 +1158,6 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { pw.println("mLocalActivePort: " + getLocalActivePort()); HdmiUtils.dumpMap(pw, "mPortIdToTvInputs:", mPortIdToTvInputs); HdmiUtils.dumpMap(pw, "mTvInputsToDeviceInfo:", mTvInputsToDeviceInfo); HdmiUtils.dumpSparseArray(pw, "mDeviceInfos:", mDeviceInfos); pw.decreaseIndent(); super.dump(pw); } Loading services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +22 −444 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java +2 −1 Original line number Diff line number Diff line Loading @@ -339,7 +339,8 @@ final class DeviceDiscoveryAction extends HdmiCecFeatureAction { // This is to manager CEC device separately in case they don't have address. if (mIsTvDevice) { tv().updateCecSwitchInfo(current.mLogicalAddress, current.mDeviceType, localDevice().mService.getHdmiCecNetwork().updateCecSwitchInfo(current.mLogicalAddress, current.mDeviceType, current.mPhysicalAddress); } increaseProcessedDeviceCount(); Loading
services/core/java/com/android/server/hdmi/HdmiCecController.java +4 −71 Original line number Diff line number Diff line Loading @@ -32,7 +32,6 @@ import android.os.Looper; import android.os.RemoteException; import android.stats.hdmi.HdmiStatsEnums; import android.util.Slog; import android.util.SparseArray; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.IndentingPrintWriter; Loading Loading @@ -97,7 +96,7 @@ final class HdmiCecController { private final Predicate<Integer> mRemoteDeviceAddressPredicate = new Predicate<Integer>() { @Override public boolean test(Integer address) { return !isAllocatedLocalDeviceAddress(address); return !mService.getHdmiCecNetwork().isAllocatedLocalDeviceAddress(address); } }; Loading @@ -118,9 +117,6 @@ final class HdmiCecController { private final HdmiControlService mService; // Stores the local CEC devices in the system. Device type is used for key. private final SparseArray<HdmiCecLocalDevice> mLocalDevices = new SparseArray<>(); // Stores recent CEC messages and HDMI Hotplug event history for debugging purpose. private final ArrayBlockingQueue<Dumpable> mMessageHistory = new ArrayBlockingQueue<>(MAX_HDMI_MESSAGE_HISTORY); Loading Loading @@ -173,12 +169,6 @@ final class HdmiCecController { nativeWrapper.setCallback(new HdmiCecCallback()); } @ServiceThreadOnly void addLocalDevice(int deviceType, HdmiCecLocalDevice device) { assertRunOnServiceThread(); mLocalDevices.put(deviceType, device); } /** * Allocate a new logical address of the given device type. Allocated * address will be reported through {@link AllocateAddressCallback}. Loading Loading @@ -268,17 +258,6 @@ final class HdmiCecController { return mNativeWrapperImpl.nativeGetPortInfos(); } /** * Return the locally hosted logical device of a given type. * * @param deviceType logical device type * @return {@link HdmiCecLocalDevice} instance if the instance of the type is available; * otherwise null. */ HdmiCecLocalDevice getLocalDevice(int deviceType) { return mLocalDevices.get(deviceType); } /** * Add a new logical address to the device. Device's HW should be notified * when a new logical address is assigned to a device, so that it can accept Loading Loading @@ -307,18 +286,9 @@ final class HdmiCecController { @ServiceThreadOnly void clearLogicalAddress() { assertRunOnServiceThread(); for (int i = 0; i < mLocalDevices.size(); ++i) { mLocalDevices.valueAt(i).clearAddress(); } mNativeWrapperImpl.nativeClearLogicalAddress(); } @ServiceThreadOnly void clearLocalDevices() { assertRunOnServiceThread(); mLocalDevices.clear(); } /** * Return the physical address of the device. * Loading Loading @@ -428,17 +398,6 @@ final class HdmiCecController { runDevicePolling(sourceAddress, pollingCandidates, retryCount, callback, allocated); } /** * Return a list of all {@link HdmiCecLocalDevice}s. * * <p>Declared as package-private. accessed by {@link HdmiControlService} only. */ @ServiceThreadOnly List<HdmiCecLocalDevice> getLocalDeviceList() { assertRunOnServiceThread(); return HdmiUtils.sparseArrayToList(mLocalDevices); } private List<Integer> pickPollCandidates(int pickStrategy) { int strategy = pickStrategy & Constants.POLL_STRATEGY_MASK; Predicate<Integer> pickPredicate = null; Loading Loading @@ -474,17 +433,6 @@ final class HdmiCecController { return pollingCandidates; } @ServiceThreadOnly private boolean isAllocatedLocalDeviceAddress(int address) { assertRunOnServiceThread(); for (int i = 0; i < mLocalDevices.size(); ++i) { if (mLocalDevices.valueAt(i).isAddressOf(address)) { return true; } } return false; } @ServiceThreadOnly private void runDevicePolling(final int sourceAddress, final List<Integer> candidates, final int retryCount, Loading Loading @@ -578,7 +526,7 @@ final class HdmiCecController { if (address == Constants.ADDR_BROADCAST) { return true; } return isAllocatedLocalDeviceAddress(address); return mService.getHdmiCecNetwork().isAllocatedLocalDeviceAddress(address); } @ServiceThreadOnly Loading Loading @@ -682,7 +630,7 @@ final class HdmiCecController { private int incomingMessageDirection(int srcAddress, int dstAddress) { boolean sourceIsLocal = false; boolean destinationIsLocal = false; for (HdmiCecLocalDevice localDevice : getLocalDeviceList()) { for (HdmiCecLocalDevice localDevice : mService.getHdmiCecNetwork().getLocalDeviceList()) { int logicalAddress = localDevice.getDeviceInfo().getLogicalAddress(); if (logicalAddress == srcAddress) { sourceIsLocal = true; Loading Loading @@ -731,24 +679,9 @@ final class HdmiCecController { } void dump(final IndentingPrintWriter pw) { final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); for (int i = 0; i < mLocalDevices.size(); ++i) { pw.println("HdmiCecLocalDevice #" + mLocalDevices.keyAt(i) + ":"); pw.increaseIndent(); mLocalDevices.valueAt(i).dump(pw); pw.println("Active Source history:"); pw.increaseIndent(); for (Dumpable activeSourceEvent : mLocalDevices.valueAt(i).getActiveSourceHistory()) { activeSourceEvent.dump(pw, sdf); } pw.decreaseIndent(); pw.decreaseIndent(); } pw.println("CEC message history:"); pw.increaseIndent(); final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); for (Dumpable record : mMessageHistory) { record.dump(pw, sdf); } Loading
services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +24 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.hdmi; import android.annotation.CallSuper; import android.annotation.Nullable; import android.hardware.hdmi.HdmiDeviceInfo; import android.hardware.hdmi.IHdmiControlCallback; Loading Loading @@ -471,8 +472,27 @@ abstract class HdmiCecLocalDevice { return false; } @CallSuper protected boolean handleReportPhysicalAddress(HdmiCecMessage message) { return false; // <Report Physical Address> is also handled in HdmiCecNetwork to update the local network // state int address = message.getSource(); // Ignore if [Device Discovery Action] is going on. if (hasAction(DeviceDiscoveryAction.class)) { Slog.i(TAG, "Ignored while Device Discovery Action is in progress: " + message); return true; } HdmiDeviceInfo cecDeviceInfo = mService.getHdmiCecNetwork().getCecDeviceInfo(address); // If no non-default display name is available for the device, request the devices OSD name. if (cecDeviceInfo.getDisplayName().equals(HdmiUtils.getDefaultDeviceName(address))) { mService.sendCecCommand( HdmiCecMessageBuilder.buildGiveOsdNameCommand(mAddress, address)); } return true; } protected boolean handleSystemAudioModeStatus(HdmiCecMessage message) { Loading Loading @@ -708,7 +728,7 @@ abstract class HdmiCecLocalDevice { } protected boolean handleSetOsdName(HdmiCecMessage message) { // The default behavior of <Set Osd Name> is doing nothing. // <Set OSD name> is also handled in HdmiCecNetwork to update the local network state return true; } Loading @@ -724,7 +744,8 @@ abstract class HdmiCecLocalDevice { } protected boolean handleReportPowerStatus(HdmiCecMessage message) { return false; // <Report Power Status> is also handled in HdmiCecNetwork to update the local network state return true; } protected boolean handleTimerStatus(HdmiCecMessage message) { Loading
services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java +7 −259 Original line number Diff line number Diff line Loading @@ -37,7 +37,6 @@ import android.os.SystemProperties; import android.provider.Settings.Global; import android.sysprop.HdmiProperties; import android.util.Slog; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; Loading @@ -54,15 +53,12 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.stream.Collectors; /** * Represent a logical device of type {@link HdmiDeviceInfo#DEVICE_AUDIO_SYSTEM} residing in Android * system. Loading Loading @@ -104,14 +100,6 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { @GuardedBy("mLock") private final HashMap<String, HdmiDeviceInfo> mTvInputsToDeviceInfo = new HashMap<>(); // Copy of mDeviceInfos to guarantee thread-safety. @GuardedBy("mLock") private List<HdmiDeviceInfo> mSafeAllDeviceInfos = Collections.emptyList(); // Map-like container of all cec devices. // device id is used as key of container. private final SparseArray<HdmiDeviceInfo> mDeviceInfos = new SparseArray<>(); // Message buffer used to buffer selected messages to process later. <Active Source> // from a source device, for instance, needs to be buffered if the device is not // discovered yet. The buffered commands are taken out and when they are ready to Loading Loading @@ -187,135 +175,6 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { return info != null; } /** * Called when a device is newly added or a new device is detected or * an existing device is updated. * * @param info device info of a new device. */ @ServiceThreadOnly final void addCecDevice(HdmiDeviceInfo info) { assertRunOnServiceThread(); HdmiDeviceInfo old = addDeviceInfo(info); if (info.getPhysicalAddress() == mService.getPhysicalAddress()) { // The addition of the device itself should not be notified. // Note that different logical address could still be the same local device. return; } if (old == null) { invokeDeviceEventListener(info, HdmiControlManager.DEVICE_EVENT_ADD_DEVICE); } else if (!old.equals(info)) { invokeDeviceEventListener(old, HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE); invokeDeviceEventListener(info, HdmiControlManager.DEVICE_EVENT_ADD_DEVICE); } } /** * Called when a device is removed or removal of device is detected. * * @param address a logical address of a device to be removed */ @ServiceThreadOnly final void removeCecDevice(int address) { assertRunOnServiceThread(); HdmiDeviceInfo info = removeDeviceInfo(HdmiDeviceInfo.idForCecDevice(address)); mCecMessageCache.flushMessagesFrom(address); invokeDeviceEventListener(info, HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE); } /** * Called when a device is updated. * * @param info device info of the updating device. */ @ServiceThreadOnly final void updateCecDevice(HdmiDeviceInfo info) { assertRunOnServiceThread(); HdmiDeviceInfo old = addDeviceInfo(info); if (old == null) { invokeDeviceEventListener(info, HdmiControlManager.DEVICE_EVENT_ADD_DEVICE); } else if (!old.equals(info)) { invokeDeviceEventListener(info, HdmiControlManager.DEVICE_EVENT_UPDATE_DEVICE); } } /** * Add a new {@link HdmiDeviceInfo}. It returns old device info which has the same * logical address as new device info's. * * @param deviceInfo a new {@link HdmiDeviceInfo} to be added. * @return {@code null} if it is new device. Otherwise, returns old {@HdmiDeviceInfo} * that has the same logical address as new one has. */ @ServiceThreadOnly @VisibleForTesting protected HdmiDeviceInfo addDeviceInfo(HdmiDeviceInfo deviceInfo) { assertRunOnServiceThread(); mService.checkLogicalAddressConflictAndReallocate(deviceInfo.getLogicalAddress()); HdmiDeviceInfo oldDeviceInfo = getCecDeviceInfo(deviceInfo.getLogicalAddress()); if (oldDeviceInfo != null) { removeDeviceInfo(deviceInfo.getId()); } mDeviceInfos.append(deviceInfo.getId(), deviceInfo); updateSafeDeviceInfoList(); return oldDeviceInfo; } /** * Remove a device info corresponding to the given {@code logicalAddress}. * It returns removed {@link HdmiDeviceInfo} if exists. * * @param id id of device to be removed * @return removed {@link HdmiDeviceInfo} it exists. Otherwise, returns {@code null} */ @ServiceThreadOnly private HdmiDeviceInfo removeDeviceInfo(int id) { assertRunOnServiceThread(); HdmiDeviceInfo deviceInfo = mDeviceInfos.get(id); if (deviceInfo != null) { mDeviceInfos.remove(id); } updateSafeDeviceInfoList(); return deviceInfo; } /** * Return a {@link HdmiDeviceInfo} corresponding to the given {@code logicalAddress}. * * @param logicalAddress logical address of the device to be retrieved * @return {@link HdmiDeviceInfo} matched with the given {@code logicalAddress}. * Returns null if no logical address matched */ @ServiceThreadOnly HdmiDeviceInfo getCecDeviceInfo(int logicalAddress) { assertRunOnServiceThread(); return mDeviceInfos.get(HdmiDeviceInfo.idForCecDevice(logicalAddress)); } @ServiceThreadOnly private void updateSafeDeviceInfoList() { assertRunOnServiceThread(); List<HdmiDeviceInfo> copiedDevices = HdmiUtils.sparseArrayToList(mDeviceInfos); synchronized (mLock) { mSafeAllDeviceInfos = copiedDevices; } } @GuardedBy("mLock") List<HdmiDeviceInfo> getSafeCecDevicesLocked() { ArrayList<HdmiDeviceInfo> infoList = new ArrayList<>(); for (HdmiDeviceInfo info : mSafeAllDeviceInfos) { infoList.add(info); } return infoList; } private void invokeDeviceEventListener(HdmiDeviceInfo info, int status) { mService.invokeDeviceEventListeners(info, status); } @Override @ServiceThreadOnly void onHotplug(int portId, boolean connected) { Loading @@ -342,7 +201,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { } // Update with TIF on the device removal. TIF callback will update // mPortIdToTvInputs and mPortIdToTvInputs. removeCecDevice(info.getLogicalAddress()); mService.getHdmiCecNetwork().removeCecDevice(this, info.getLogicalAddress()); } } Loading Loading @@ -399,7 +258,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { boolean lastSystemAudioControlStatus = SystemProperties.getBoolean(Constants.PROPERTY_LAST_SYSTEM_AUDIO_CONTROL, true); systemAudioControlOnPowerOn(systemAudioControlOnPowerOnProp, lastSystemAudioControlStatus); clearDeviceInfoList(); mService.getHdmiCecNetwork().clearDeviceList(); launchDeviceDiscovery(); startQueuedActions(); } Loading Loading @@ -458,7 +317,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { // If the new Active Source is under the current device, check if the device info and the TV // input is ready to switch to the new Active Source. If not ready, buffer the cec command // to handle later when the device is ready. HdmiDeviceInfo info = getCecDeviceInfo(logicalAddress); HdmiDeviceInfo info = mService.getHdmiCecNetwork().getCecDeviceInfo(logicalAddress); if (info == null) { HdmiLogger.debug("Device info %X not found; buffering the command", logicalAddress); mDelayedMessageBuffer.add(message); Loading @@ -472,79 +331,6 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { return true; } @Override @ServiceThreadOnly protected boolean handleReportPhysicalAddress(HdmiCecMessage message) { assertRunOnServiceThread(); int path = HdmiUtils.twoBytesToInt(message.getParams()); int address = message.getSource(); int type = message.getParams()[2]; // Ignore if [Device Discovery Action] is going on. if (hasAction(DeviceDiscoveryAction.class)) { Slog.i(TAG, "Ignored while Device Discovery Action is in progress: " + message); return true; } // Update the device info with TIF, note that the same device info could have added in // device discovery and we do not want to override it with default OSD name. Therefore we // need the following check to skip redundant device info updating. HdmiDeviceInfo oldDevice = getCecDeviceInfo(address); if (oldDevice == null || oldDevice.getPhysicalAddress() != path) { addCecDevice(new HdmiDeviceInfo( address, path, mService.pathToPortId(path), type, Constants.UNKNOWN_VENDOR_ID, "")); // if we are adding a new device info, send out a give osd name command // to update the name of the device in TIF mService.sendCecCommand( HdmiCecMessageBuilder.buildGiveOsdNameCommand(mAddress, address)); return true; } Slog.w(TAG, "Device info exists. Not updating on Physical Address."); return true; } @Override protected boolean handleReportPowerStatus(HdmiCecMessage command) { int newStatus = command.getParams()[0] & 0xFF; updateDevicePowerStatus(command.getSource(), newStatus); return true; } @Override @ServiceThreadOnly protected boolean handleSetOsdName(HdmiCecMessage message) { int source = message.getSource(); String osdName; HdmiDeviceInfo deviceInfo = getCecDeviceInfo(source); // If the device is not in device list, ignore it. if (deviceInfo == null) { Slog.i(TAG, "No source device info for <Set Osd Name>." + message); return true; } try { osdName = new String(message.getParams(), "US-ASCII"); } catch (UnsupportedEncodingException e) { Slog.e(TAG, "Invalid <Set Osd Name> request:" + message, e); return true; } if (deviceInfo.getDisplayName() != null && deviceInfo.getDisplayName().equals(osdName)) { Slog.d(TAG, "Ignore incoming <Set Osd Name> having same osd name:" + message); return true; } Slog.d(TAG, "Updating device OSD name from " + deviceInfo.getDisplayName() + " to " + osdName); updateCecDevice(new HdmiDeviceInfo(deviceInfo.getLogicalAddress(), deviceInfo.getPhysicalAddress(), deviceInfo.getPortId(), deviceInfo.getDeviceType(), deviceInfo.getVendorId(), osdName)); return true; } @Override @ServiceThreadOnly protected boolean handleInitiateArc(HdmiCecMessage message) { Loading Loading @@ -864,14 +650,9 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { != HdmiUtils.TARGET_NOT_UNDER_LOCAL_DEVICE) { return true; } boolean isDeviceInCecDeviceList = false; for (HdmiDeviceInfo info : HdmiUtils.sparseArrayToList(mDeviceInfos)) { if (info.getPhysicalAddress() == sourcePhysicalAddress) { isDeviceInCecDeviceList = true; break; } } if (!isDeviceInCecDeviceList) { HdmiDeviceInfo safeDeviceInfoByPath = mService.getHdmiCecNetwork().getSafeDeviceInfoByPath(sourcePhysicalAddress); if (safeDeviceInfoByPath == null) { switchInputOnReceivingNewActivePath(sourcePhysicalAddress); } } Loading Loading @@ -1345,24 +1126,6 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { routeToInputFromPortId(getRoutingPort()); } protected void updateDevicePowerStatus(int logicalAddress, int newPowerStatus) { HdmiDeviceInfo info = getCecDeviceInfo(logicalAddress); if (info == null) { Slog.w(TAG, "Can not update power status of non-existing device:" + logicalAddress); return; } if (info.getDevicePowerStatus() == newPowerStatus) { return; } HdmiDeviceInfo newInfo = HdmiUtils.cloneHdmiDeviceInfo(info, newPowerStatus); // addDeviceInfo replaces old device info with new one if exists. addDeviceInfo(newInfo); invokeDeviceEventListener(newInfo, HdmiControlManager.DEVICE_EVENT_UPDATE_DEVICE); } @ServiceThreadOnly private void launchDeviceDiscovery() { assertRunOnServiceThread(); Loading @@ -1375,27 +1138,13 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { @Override public void onDeviceDiscoveryDone(List<HdmiDeviceInfo> deviceInfos) { for (HdmiDeviceInfo info : deviceInfos) { addCecDevice(info); mService.getHdmiCecNetwork().addCecDevice(info); } } }); addAndStartAction(action); } // Clear all device info. @ServiceThreadOnly private void clearDeviceInfoList() { assertRunOnServiceThread(); for (HdmiDeviceInfo info : HdmiUtils.sparseArrayToList(mDeviceInfos)) { if (info.getPhysicalAddress() == mService.getPhysicalAddress()) { continue; } invokeDeviceEventListener(info, HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE); } mDeviceInfos.clear(); updateSafeDeviceInfoList(); } @Override protected void dump(IndentingPrintWriter pw) { pw.println("HdmiCecLocalDeviceAudioSystem:"); Loading @@ -1409,7 +1158,6 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { pw.println("mLocalActivePort: " + getLocalActivePort()); HdmiUtils.dumpMap(pw, "mPortIdToTvInputs:", mPortIdToTvInputs); HdmiUtils.dumpMap(pw, "mTvInputsToDeviceInfo:", mTvInputsToDeviceInfo); HdmiUtils.dumpSparseArray(pw, "mDeviceInfos:", mDeviceInfos); pw.decreaseIndent(); super.dump(pw); } Loading
services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +22 −444 File changed.Preview size limit exceeded, changes collapsed. Show changes