Loading services/core/java/com/android/server/tv/TvInputManagerService.java +102 −0 Original line number Original line Diff line number Diff line Loading @@ -155,6 +155,12 @@ public final class TvInputManagerService extends SystemService { // ID of the current user. // ID of the current user. @GuardedBy("mLock") @GuardedBy("mLock") private int mCurrentUserId = UserHandle.USER_SYSTEM; private int mCurrentUserId = UserHandle.USER_SYSTEM; @GuardedBy("mLock") // ID of the current input displayed on the screen. private String mCurrentInputId = null; @GuardedBy("mLock") // SessionState of the currently active TIS session. private SessionState mCurrentSessionState = null; // IDs of the running profiles. Their parent user ID should be mCurrentUserId. // IDs of the running profiles. Their parent user ID should be mCurrentUserId. @GuardedBy("mLock") @GuardedBy("mLock") private final Set<Integer> mRunningProfiles = new HashSet<>(); private final Set<Integer> mRunningProfiles = new HashSet<>(); Loading Loading @@ -884,6 +890,10 @@ public final class TvInputManagerService extends SystemService { sessionState.session = null; sessionState.session = null; } } } } logExternalInputEvent(FrameworkStatsLog.EXTERNAL_TV_INPUT_EVENT__EVENT_TYPE__RELEASED, mCurrentInputId, sessionState); mCurrentInputId = null; mCurrentSessionState = null; removeSessionStateLocked(sessionToken, userId); removeSessionStateLocked(sessionToken, userId); return sessionState; return sessionState; } } Loading Loading @@ -1065,6 +1075,7 @@ public final class TvInputManagerService extends SystemService { Slog.e(TAG, "failed to set input info - unknown input id " + inputId); Slog.e(TAG, "failed to set input info - unknown input id " + inputId); return; return; } } boolean currentCecTvInputInfoUpdated = isCurrentCecTvInputInfoUpdate(userState, inputInfo); inputState.info = inputInfo; inputState.info = inputInfo; inputState.uid = getInputUid(inputInfo); inputState.uid = getInputUid(inputInfo); ServiceState serviceState = userState.serviceStateMap.get(inputInfo.getComponent()); ServiceState serviceState = userState.serviceStateMap.get(inputInfo.getComponent()); Loading @@ -1073,6 +1084,12 @@ public final class TvInputManagerService extends SystemService { mTvInputHardwareManager.updateInputInfo(inputInfo); mTvInputHardwareManager.updateInputInfo(inputInfo); } } if (currentCecTvInputInfoUpdated) { logExternalInputEvent( FrameworkStatsLog.EXTERNAL_TV_INPUT_EVENT__EVENT_TYPE__DEVICE_INFO_UPDATED, mCurrentInputId, mCurrentSessionState); } int n = userState.mCallbacks.beginBroadcast(); int n = userState.mCallbacks.beginBroadcast(); for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) { try { try { Loading @@ -1084,6 +1101,29 @@ public final class TvInputManagerService extends SystemService { userState.mCallbacks.finishBroadcast(); userState.mCallbacks.finishBroadcast(); } } @GuardedBy("mLock") private boolean isCurrentCecTvInputInfoUpdate(UserState userState, TvInputInfo newInputInfo) { if (newInputInfo == null || newInputInfo.getId() == null || !newInputInfo.getId().equals(mCurrentInputId)) { return false; } if (newInputInfo.getHdmiDeviceInfo() == null || !newInputInfo.getHdmiDeviceInfo().isCecDevice()) { return false; } TvInputState inputState = userState.inputMap.get(mCurrentInputId); if (inputState == null || inputState.info == null) { return false; } if (inputState.info.getHdmiDeviceInfo() == null || !inputState.info.getHdmiDeviceInfo().isCecDevice()) { return false; } int newVendorId = newInputInfo.getHdmiDeviceInfo().getVendorId(), currentVendorId = inputState.info.getHdmiDeviceInfo().getVendorId(); return newVendorId != currentVendorId; } @GuardedBy("mLock") @GuardedBy("mLock") private void setStateLocked(String inputId, int state, int userId) { private void setStateLocked(String inputId, int state, int userId) { UserState userState = getOrCreateUserStateLocked(userId); UserState userState = getOrCreateUserStateLocked(userId); Loading @@ -1101,6 +1141,24 @@ public final class TvInputManagerService extends SystemService { return; return; } } if (oldState != state) { if (oldState != state) { if (inputId.equals(mCurrentInputId)) { logExternalInputEvent( FrameworkStatsLog .EXTERNAL_TV_INPUT_EVENT__EVENT_TYPE__CONNECTION_STATE_CHANGED, mCurrentInputId, mCurrentSessionState); } else if (mCurrentInputId != null) { TvInputInfo currentInputInfo = userState.inputMap.get(mCurrentInputId).info; if (currentInputInfo != null && currentInputInfo.getHdmiDeviceInfo() != null && inputId.equals(currentInputInfo.getParentId())) { logExternalInputEvent( FrameworkStatsLog .EXTERNAL_TV_INPUT_EVENT__EVENT_TYPE__CONNECTION_STATE_CHANGED, inputId, mCurrentSessionState); if (state == INPUT_STATE_CONNECTED_STANDBY) { mCurrentInputId = currentInputInfo.getParentId(); } } } notifyInputStateChangedLocked(userState, inputId, state, null); notifyInputStateChangedLocked(userState, inputId, state, null); } } } } Loading Loading @@ -1764,10 +1822,18 @@ public final class TvInputManagerService extends SystemService { UserState userState = getOrCreateUserStateLocked(resolvedUserId); UserState userState = getOrCreateUserStateLocked(resolvedUserId); SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, userState); userState); if (mCurrentInputId == null || !mCurrentInputId.equals(sessionState.inputId)) { mCurrentInputId = sessionState.inputId; logExternalInputEvent( FrameworkStatsLog.EXTERNAL_TV_INPUT_EVENT__EVENT_TYPE__TUNED, sessionState.inputId, sessionState); } if (!sessionState.isCurrent if (!sessionState.isCurrent || !Objects.equals(sessionState.currentChannel, channelUri)) { || !Objects.equals(sessionState.currentChannel, channelUri)) { sessionState.isCurrent = true; sessionState.isCurrent = true; sessionState.currentChannel = channelUri; sessionState.currentChannel = channelUri; mCurrentSessionState = sessionState; notifyCurrentChannelInfosUpdatedLocked(userState); notifyCurrentChannelInfosUpdatedLocked(userState); } } if (TvContract.isChannelUriForPassthroughInput(channelUri)) { if (TvContract.isChannelUriForPassthroughInput(channelUri)) { Loading Loading @@ -2990,6 +3056,30 @@ public final class TvInputManagerService extends SystemService { hdmiPort); hdmiPort); } } private void logExternalInputEvent(int eventType, String inputId, SessionState sessionState) { UserState userState = getOrCreateUserStateLocked(sessionState.userId); TvInputState tvInputState = userState.inputMap.get(inputId); TvInputInfo tvInputInfo = tvInputState.info; int inputState = tvInputState.state; int inputType = tvInputInfo.getType(); // For non-CEC input, the value of vendorId is 0. int vendorId = 0; // For non-HDMI input, the value of hdmiPort is 0. int hdmiPort = 0; String tifSessionId = sessionState.sessionId; if (tvInputInfo.getType() == TvInputInfo.TYPE_HDMI) { HdmiDeviceInfo hdmiDeviceInfo = tvInputInfo.getHdmiDeviceInfo(); if (hdmiDeviceInfo != null) { vendorId = hdmiDeviceInfo.getVendorId(); hdmiPort = hdmiDeviceInfo.getPortId(); } } FrameworkStatsLog.write(FrameworkStatsLog.EXTERNAL_TV_INPUT_EVENT, eventType, inputState, inputType, vendorId, hdmiPort, tifSessionId); } private static final class UserState { private static final class UserState { // A mapping from the TV input id to its TvInputState. // A mapping from the TV input id to its TvInputState. private Map<String, TvInputState> inputMap = new HashMap<>(); private Map<String, TvInputState> inputMap = new HashMap<>(); Loading Loading @@ -3353,6 +3443,16 @@ public final class TvInputManagerService extends SystemService { synchronized (mLock) { synchronized (mLock) { mTvInputHardwareManager.addHdmiInput(id, inputInfo); mTvInputHardwareManager.addHdmiInput(id, inputInfo); addHardwareInputLocked(inputInfo); addHardwareInputLocked(inputInfo); // catch the use case when a CEC device is unplugged from // an HDMI port, then plugged in to the same HDMI port. if (mCurrentInputId != null && mCurrentSessionState != null && mCurrentInputId.equals(inputInfo.getParentId()) && inputInfo.getId().equals(mCurrentSessionState.inputId)) { logExternalInputEvent( FrameworkStatsLog.EXTERNAL_TV_INPUT_EVENT__EVENT_TYPE__TUNED, inputInfo.getId(), mCurrentSessionState); mCurrentInputId = inputInfo.getId(); } } } } finally { } finally { Binder.restoreCallingIdentity(identity); Binder.restoreCallingIdentity(identity); Loading Loading @@ -3455,6 +3555,8 @@ public final class TvInputManagerService extends SystemService { UserState userState = getOrCreateUserStateLocked(mSessionState.userId); UserState userState = getOrCreateUserStateLocked(mSessionState.userId); mSessionState.isCurrent = true; mSessionState.isCurrent = true; mSessionState.currentChannel = channelUri; mSessionState.currentChannel = channelUri; mCurrentSessionState = mSessionState; mCurrentInputId = mSessionState.inputId; notifyCurrentChannelInfosUpdatedLocked(userState); notifyCurrentChannelInfosUpdatedLocked(userState); } } } catch (RemoteException e) { } catch (RemoteException e) { Loading Loading
services/core/java/com/android/server/tv/TvInputManagerService.java +102 −0 Original line number Original line Diff line number Diff line Loading @@ -155,6 +155,12 @@ public final class TvInputManagerService extends SystemService { // ID of the current user. // ID of the current user. @GuardedBy("mLock") @GuardedBy("mLock") private int mCurrentUserId = UserHandle.USER_SYSTEM; private int mCurrentUserId = UserHandle.USER_SYSTEM; @GuardedBy("mLock") // ID of the current input displayed on the screen. private String mCurrentInputId = null; @GuardedBy("mLock") // SessionState of the currently active TIS session. private SessionState mCurrentSessionState = null; // IDs of the running profiles. Their parent user ID should be mCurrentUserId. // IDs of the running profiles. Their parent user ID should be mCurrentUserId. @GuardedBy("mLock") @GuardedBy("mLock") private final Set<Integer> mRunningProfiles = new HashSet<>(); private final Set<Integer> mRunningProfiles = new HashSet<>(); Loading Loading @@ -884,6 +890,10 @@ public final class TvInputManagerService extends SystemService { sessionState.session = null; sessionState.session = null; } } } } logExternalInputEvent(FrameworkStatsLog.EXTERNAL_TV_INPUT_EVENT__EVENT_TYPE__RELEASED, mCurrentInputId, sessionState); mCurrentInputId = null; mCurrentSessionState = null; removeSessionStateLocked(sessionToken, userId); removeSessionStateLocked(sessionToken, userId); return sessionState; return sessionState; } } Loading Loading @@ -1065,6 +1075,7 @@ public final class TvInputManagerService extends SystemService { Slog.e(TAG, "failed to set input info - unknown input id " + inputId); Slog.e(TAG, "failed to set input info - unknown input id " + inputId); return; return; } } boolean currentCecTvInputInfoUpdated = isCurrentCecTvInputInfoUpdate(userState, inputInfo); inputState.info = inputInfo; inputState.info = inputInfo; inputState.uid = getInputUid(inputInfo); inputState.uid = getInputUid(inputInfo); ServiceState serviceState = userState.serviceStateMap.get(inputInfo.getComponent()); ServiceState serviceState = userState.serviceStateMap.get(inputInfo.getComponent()); Loading @@ -1073,6 +1084,12 @@ public final class TvInputManagerService extends SystemService { mTvInputHardwareManager.updateInputInfo(inputInfo); mTvInputHardwareManager.updateInputInfo(inputInfo); } } if (currentCecTvInputInfoUpdated) { logExternalInputEvent( FrameworkStatsLog.EXTERNAL_TV_INPUT_EVENT__EVENT_TYPE__DEVICE_INFO_UPDATED, mCurrentInputId, mCurrentSessionState); } int n = userState.mCallbacks.beginBroadcast(); int n = userState.mCallbacks.beginBroadcast(); for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) { try { try { Loading @@ -1084,6 +1101,29 @@ public final class TvInputManagerService extends SystemService { userState.mCallbacks.finishBroadcast(); userState.mCallbacks.finishBroadcast(); } } @GuardedBy("mLock") private boolean isCurrentCecTvInputInfoUpdate(UserState userState, TvInputInfo newInputInfo) { if (newInputInfo == null || newInputInfo.getId() == null || !newInputInfo.getId().equals(mCurrentInputId)) { return false; } if (newInputInfo.getHdmiDeviceInfo() == null || !newInputInfo.getHdmiDeviceInfo().isCecDevice()) { return false; } TvInputState inputState = userState.inputMap.get(mCurrentInputId); if (inputState == null || inputState.info == null) { return false; } if (inputState.info.getHdmiDeviceInfo() == null || !inputState.info.getHdmiDeviceInfo().isCecDevice()) { return false; } int newVendorId = newInputInfo.getHdmiDeviceInfo().getVendorId(), currentVendorId = inputState.info.getHdmiDeviceInfo().getVendorId(); return newVendorId != currentVendorId; } @GuardedBy("mLock") @GuardedBy("mLock") private void setStateLocked(String inputId, int state, int userId) { private void setStateLocked(String inputId, int state, int userId) { UserState userState = getOrCreateUserStateLocked(userId); UserState userState = getOrCreateUserStateLocked(userId); Loading @@ -1101,6 +1141,24 @@ public final class TvInputManagerService extends SystemService { return; return; } } if (oldState != state) { if (oldState != state) { if (inputId.equals(mCurrentInputId)) { logExternalInputEvent( FrameworkStatsLog .EXTERNAL_TV_INPUT_EVENT__EVENT_TYPE__CONNECTION_STATE_CHANGED, mCurrentInputId, mCurrentSessionState); } else if (mCurrentInputId != null) { TvInputInfo currentInputInfo = userState.inputMap.get(mCurrentInputId).info; if (currentInputInfo != null && currentInputInfo.getHdmiDeviceInfo() != null && inputId.equals(currentInputInfo.getParentId())) { logExternalInputEvent( FrameworkStatsLog .EXTERNAL_TV_INPUT_EVENT__EVENT_TYPE__CONNECTION_STATE_CHANGED, inputId, mCurrentSessionState); if (state == INPUT_STATE_CONNECTED_STANDBY) { mCurrentInputId = currentInputInfo.getParentId(); } } } notifyInputStateChangedLocked(userState, inputId, state, null); notifyInputStateChangedLocked(userState, inputId, state, null); } } } } Loading Loading @@ -1764,10 +1822,18 @@ public final class TvInputManagerService extends SystemService { UserState userState = getOrCreateUserStateLocked(resolvedUserId); UserState userState = getOrCreateUserStateLocked(resolvedUserId); SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, SessionState sessionState = getSessionStateLocked(sessionToken, callingUid, userState); userState); if (mCurrentInputId == null || !mCurrentInputId.equals(sessionState.inputId)) { mCurrentInputId = sessionState.inputId; logExternalInputEvent( FrameworkStatsLog.EXTERNAL_TV_INPUT_EVENT__EVENT_TYPE__TUNED, sessionState.inputId, sessionState); } if (!sessionState.isCurrent if (!sessionState.isCurrent || !Objects.equals(sessionState.currentChannel, channelUri)) { || !Objects.equals(sessionState.currentChannel, channelUri)) { sessionState.isCurrent = true; sessionState.isCurrent = true; sessionState.currentChannel = channelUri; sessionState.currentChannel = channelUri; mCurrentSessionState = sessionState; notifyCurrentChannelInfosUpdatedLocked(userState); notifyCurrentChannelInfosUpdatedLocked(userState); } } if (TvContract.isChannelUriForPassthroughInput(channelUri)) { if (TvContract.isChannelUriForPassthroughInput(channelUri)) { Loading Loading @@ -2990,6 +3056,30 @@ public final class TvInputManagerService extends SystemService { hdmiPort); hdmiPort); } } private void logExternalInputEvent(int eventType, String inputId, SessionState sessionState) { UserState userState = getOrCreateUserStateLocked(sessionState.userId); TvInputState tvInputState = userState.inputMap.get(inputId); TvInputInfo tvInputInfo = tvInputState.info; int inputState = tvInputState.state; int inputType = tvInputInfo.getType(); // For non-CEC input, the value of vendorId is 0. int vendorId = 0; // For non-HDMI input, the value of hdmiPort is 0. int hdmiPort = 0; String tifSessionId = sessionState.sessionId; if (tvInputInfo.getType() == TvInputInfo.TYPE_HDMI) { HdmiDeviceInfo hdmiDeviceInfo = tvInputInfo.getHdmiDeviceInfo(); if (hdmiDeviceInfo != null) { vendorId = hdmiDeviceInfo.getVendorId(); hdmiPort = hdmiDeviceInfo.getPortId(); } } FrameworkStatsLog.write(FrameworkStatsLog.EXTERNAL_TV_INPUT_EVENT, eventType, inputState, inputType, vendorId, hdmiPort, tifSessionId); } private static final class UserState { private static final class UserState { // A mapping from the TV input id to its TvInputState. // A mapping from the TV input id to its TvInputState. private Map<String, TvInputState> inputMap = new HashMap<>(); private Map<String, TvInputState> inputMap = new HashMap<>(); Loading Loading @@ -3353,6 +3443,16 @@ public final class TvInputManagerService extends SystemService { synchronized (mLock) { synchronized (mLock) { mTvInputHardwareManager.addHdmiInput(id, inputInfo); mTvInputHardwareManager.addHdmiInput(id, inputInfo); addHardwareInputLocked(inputInfo); addHardwareInputLocked(inputInfo); // catch the use case when a CEC device is unplugged from // an HDMI port, then plugged in to the same HDMI port. if (mCurrentInputId != null && mCurrentSessionState != null && mCurrentInputId.equals(inputInfo.getParentId()) && inputInfo.getId().equals(mCurrentSessionState.inputId)) { logExternalInputEvent( FrameworkStatsLog.EXTERNAL_TV_INPUT_EVENT__EVENT_TYPE__TUNED, inputInfo.getId(), mCurrentSessionState); mCurrentInputId = inputInfo.getId(); } } } } finally { } finally { Binder.restoreCallingIdentity(identity); Binder.restoreCallingIdentity(identity); Loading Loading @@ -3455,6 +3555,8 @@ public final class TvInputManagerService extends SystemService { UserState userState = getOrCreateUserStateLocked(mSessionState.userId); UserState userState = getOrCreateUserStateLocked(mSessionState.userId); mSessionState.isCurrent = true; mSessionState.isCurrent = true; mSessionState.currentChannel = channelUri; mSessionState.currentChannel = channelUri; mCurrentSessionState = mSessionState; mCurrentInputId = mSessionState.inputId; notifyCurrentChannelInfosUpdatedLocked(userState); notifyCurrentChannelInfosUpdatedLocked(userState); } } } catch (RemoteException e) { } catch (RemoteException e) { Loading