Methods Summary |
---|
void | addAndStartAction(HdmiCecFeatureAction action)
assertRunOnServiceThread();
mActions.add(action);
if (mService.isPowerStandbyOrTransient()) {
Slog.i(TAG, "Not ready to start action. Queued for deferred start:" + action);
return;
}
action.start();
|
protected void | assertRunOnServiceThread()
if (Looper.myLooper() != mService.getServiceLooper()) {
throw new IllegalStateException("Should run on service thread.");
}
|
protected boolean | canGoToStandby()Returns true if the local device allows the system to be put to standby.
The default implementation returns true.
return true;
|
protected void | checkIfPendingActionsCleared()
if (mActions.isEmpty() && mPendingActionClearedCallback != null) {
PendingActionClearedCallback callback = mPendingActionClearedCallback;
// To prevent from calling the callback again during handling the callback itself.
mPendingActionClearedCallback = null;
callback.onCleared(this);
}
|
void | clearAddress()
assertRunOnServiceThread();
mAddress = Constants.ADDR_UNREGISTERED;
|
static com.android.server.hdmi.HdmiCecLocalDevice | create(HdmiControlService service, int deviceType)
switch (deviceType) {
case HdmiDeviceInfo.DEVICE_TV:
return new HdmiCecLocalDeviceTv(service);
case HdmiDeviceInfo.DEVICE_PLAYBACK:
return new HdmiCecLocalDevicePlayback(service);
default:
return null;
}
|
protected void | disableDevice(boolean initiatedByCec, com.android.server.hdmi.HdmiCecLocalDevice$PendingActionClearedCallback origialCallback)Disable device. {@code callback} is used to get notified when all pending
actions are completed or timeout is issued.
mPendingActionClearedCallback = new PendingActionClearedCallback() {
@Override
public void onCleared(HdmiCecLocalDevice device) {
mHandler.removeMessages(MSG_DISABLE_DEVICE_TIMEOUT);
origialCallback.onCleared(device);
}
};
mHandler.sendMessageDelayed(Message.obtain(mHandler, MSG_DISABLE_DEVICE_TIMEOUT),
DEVICE_CLEANUP_TIMEOUT);
|
boolean | dispatchMessage(HdmiCecMessage message)Dispatch incoming message.
assertRunOnServiceThread();
int dest = message.getDestination();
if (dest != mAddress && dest != Constants.ADDR_BROADCAST) {
return false;
}
// Cache incoming message. Note that it caches only white-listed one.
mCecMessageCache.cacheMessage(message);
return onMessage(message);
|
private boolean | dispatchMessageToAction(HdmiCecMessage message)
assertRunOnServiceThread();
boolean processed = false;
// Use copied action list in that processCommand may remove itself.
for (HdmiCecFeatureAction action : new ArrayList<>(mActions)) {
// Iterates all actions to check whether incoming message is consumed.
boolean result = action.processCommand(message);
processed = processed || result;
}
return processed;
|
protected void | dump(com.android.internal.util.IndentingPrintWriter pw)Dump internal status of HdmiCecLocalDevice object.
pw.println("mDeviceType: " + mDeviceType);
pw.println("mAddress: " + mAddress);
pw.println("mPreferredAddress: " + mPreferredAddress);
pw.println("mDeviceInfo: " + mDeviceInfo);
pw.println("mActiveSource: " + mActiveSource);
pw.println(String.format("mActiveRoutingPath: 0x%04x", mActiveRoutingPath));
|
java.util.List | getActions(java.lang.Class clazz)
assertRunOnServiceThread();
List<T> actions = Collections.<T>emptyList();
for (HdmiCecFeatureAction action : mActions) {
if (action.getClass().equals(clazz)) {
if (actions.isEmpty()) {
actions = new ArrayList<T>();
}
actions.add((T) action);
}
}
return actions;
|
int | getActivePath()
synchronized (mLock) {
return mActiveRoutingPath;
}
|
int | getActivePortId()Returns the ID of the active HDMI port. The active port is the one that has the active
routing path connected to it directly or indirectly under the device hierarchy.
synchronized (mLock) {
return mService.pathToPortId(mActiveRoutingPath);
}
|
com.android.server.hdmi.HdmiCecLocalDevice$ActiveSource | getActiveSource()
synchronized (mLock) {
return mActiveSource;
}
|
HdmiCecMessageCache | getCecMessageCache()
assertRunOnServiceThread();
return mCecMessageCache;
|
android.hardware.hdmi.HdmiDeviceInfo | getDeviceInfo()
assertRunOnServiceThread();
return mDeviceInfo;
|
protected abstract int | getPreferredAddress()Get the preferred logical address from system properties.
|
final HdmiControlService | getService()
return mService;
|
int | getType()
return mDeviceType;
|
protected boolean | handleActiveSource(HdmiCecMessage message)
return false;
|
final void | handleAddressAllocated(int logicalAddress, int reason)
assertRunOnServiceThread();
mAddress = mPreferredAddress = logicalAddress;
onAddressAllocated(logicalAddress, reason);
setPreferredAddress(logicalAddress);
|
private void | handleDisableDeviceTimeout()
assertRunOnServiceThread();
// If all actions are not cleared in DEVICE_CLEANUP_TIMEOUT, enforce to finish them.
// onCleard will be called at the last action's finish method.
Iterator<HdmiCecFeatureAction> iter = mActions.iterator();
while (iter.hasNext()) {
HdmiCecFeatureAction action = iter.next();
action.finish(false);
iter.remove();
}
|
protected boolean | handleGetCecVersion(HdmiCecMessage message)
assertRunOnServiceThread();
int version = mService.getCecVersion();
HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildCecVersion(message.getDestination(),
message.getSource(), version);
mService.sendCecCommand(cecMessage);
return true;
|
protected boolean | handleGetMenuLanguage(HdmiCecMessage message)
assertRunOnServiceThread();
Slog.w(TAG, "Only TV can handle <Get Menu Language>:" + message.toString());
// 'return false' will cause to reply with <Feature Abort>.
return false;
|
protected boolean | handleGiveDevicePowerStatus(HdmiCecMessage message)
mService.sendCecCommand(HdmiCecMessageBuilder.buildReportPowerStatus(
mAddress, message.getSource(), mService.getPowerStatus()));
return true;
|
protected boolean | handleGiveDeviceVendorId()
assertRunOnServiceThread();
int vendorId = mService.getVendorId();
HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildDeviceVendorIdCommand(
mAddress, vendorId);
mService.sendCecCommand(cecMessage);
return true;
|
protected boolean | handleGiveOsdName(HdmiCecMessage message)
assertRunOnServiceThread();
// Note that since this method is called after logical address allocation is done,
// mDeviceInfo should not be null.
HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildSetOsdNameCommand(
mAddress, message.getSource(), mDeviceInfo.getDisplayName());
if (cecMessage != null) {
mService.sendCecCommand(cecMessage);
} else {
Slog.w(TAG, "Failed to build <Get Osd Name>:" + mDeviceInfo.getDisplayName());
}
return true;
|
protected boolean | handleGivePhysicalAddress()
assertRunOnServiceThread();
int physicalAddress = mService.getPhysicalAddress();
HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
mAddress, physicalAddress, mDeviceType);
mService.sendCecCommand(cecMessage);
return true;
|
protected boolean | handleImageViewOn(HdmiCecMessage message)
return false;
|
protected boolean | handleInactiveSource(HdmiCecMessage message)
return false;
|
protected boolean | handleInitiateArc(HdmiCecMessage message)
return false;
|
protected boolean | handleMenuRequest(HdmiCecMessage message)
// Always report menu active to receive Remote Control.
mService.sendCecCommand(HdmiCecMessageBuilder.buildReportMenuStatus(
mAddress, message.getSource(), Constants.MENU_STATE_ACTIVATED));
return true;
|
protected boolean | handleMenuStatus(HdmiCecMessage message)
return false;
|
protected boolean | handleRecordStatus(HdmiCecMessage message)
return false;
|
protected boolean | handleRecordTvScreen(HdmiCecMessage message)
// The default behavior of <Record TV Screen> is replying <Feature Abort> with
// "Cannot provide source".
mService.maySendFeatureAbortCommand(message, Constants.ABORT_CANNOT_PROVIDE_SOURCE);
return true;
|
protected boolean | handleReportAudioStatus(HdmiCecMessage message)
return false;
|
protected boolean | handleReportPhysicalAddress(HdmiCecMessage message)
return false;
|
protected boolean | handleReportPowerStatus(HdmiCecMessage message)
return false;
|
protected boolean | handleRequestActiveSource(HdmiCecMessage message)
return false;
|
protected boolean | handleRoutingChange(HdmiCecMessage message)
return false;
|
protected boolean | handleRoutingInformation(HdmiCecMessage message)
return false;
|
protected boolean | handleSetOsdName(HdmiCecMessage message)
// The default behavior of <Set Osd Name> is doing nothing.
return true;
|
protected boolean | handleSetStreamPath(HdmiCecMessage message)
return false;
|
protected boolean | handleSetSystemAudioMode(HdmiCecMessage message)
return false;
|
protected boolean | handleStandby(HdmiCecMessage message)
assertRunOnServiceThread();
// Seq #12
if (mService.isControlEnabled() && !mService.isProhibitMode()
&& mService.isPowerOnOrTransient()) {
mService.standby();
return true;
}
return false;
|
protected boolean | handleSystemAudioModeStatus(HdmiCecMessage message)
return false;
|
protected boolean | handleTerminateArc(HdmiCecMessage message)
return false;
|
protected boolean | handleTextViewOn(HdmiCecMessage message)
return false;
|
protected boolean | handleTimerClearedStatus(HdmiCecMessage message)
return false;
|
protected boolean | handleTimerStatus(HdmiCecMessage message)
return false;
|
protected boolean | handleUserControlPressed(HdmiCecMessage message)
assertRunOnServiceThread();
mHandler.removeMessages(MSG_USER_CONTROL_RELEASE_TIMEOUT);
if (mService.isPowerOnOrTransient() && isPowerOffOrToggleCommand(message)) {
mService.standby();
return true;
} else if (mService.isPowerStandbyOrTransient() && isPowerOnOrToggleCommand(message)) {
mService.wakeUp();
return true;
}
final long downTime = SystemClock.uptimeMillis();
final byte[] params = message.getParams();
final int keycode = HdmiCecKeycode.cecKeycodeAndParamsToAndroidKey(params);
int keyRepeatCount = 0;
if (mLastKeycode != HdmiCecKeycode.UNSUPPORTED_KEYCODE) {
if (keycode == mLastKeycode) {
keyRepeatCount = mLastKeyRepeatCount + 1;
} else {
injectKeyEvent(downTime, KeyEvent.ACTION_UP, mLastKeycode, 0);
}
}
mLastKeycode = keycode;
mLastKeyRepeatCount = keyRepeatCount;
if (keycode != HdmiCecKeycode.UNSUPPORTED_KEYCODE) {
injectKeyEvent(downTime, KeyEvent.ACTION_DOWN, keycode, keyRepeatCount);
mHandler.sendMessageDelayed(Message.obtain(mHandler, MSG_USER_CONTROL_RELEASE_TIMEOUT),
FOLLOWER_SAFETY_TIMEOUT);
return true;
}
return false;
|
protected boolean | handleUserControlReleased()
assertRunOnServiceThread();
mHandler.removeMessages(MSG_USER_CONTROL_RELEASE_TIMEOUT);
mLastKeyRepeatCount = 0;
if (mLastKeycode != HdmiCecKeycode.UNSUPPORTED_KEYCODE) {
final long upTime = SystemClock.uptimeMillis();
injectKeyEvent(upTime, KeyEvent.ACTION_UP, mLastKeycode, 0);
mLastKeycode = HdmiCecKeycode.UNSUPPORTED_KEYCODE;
return true;
}
return false;
|
protected boolean | handleVendorCommand(HdmiCecMessage message)
if (!mService.invokeVendorCommandListenersOnReceived(mDeviceType, message.getSource(),
message.getDestination(), message.getParams(), false)) {
// Vendor command listener may not have been registered yet. Respond with
// <Feature Abort> [NOT_IN_CORRECT_MODE] so that the sender can try again later.
mService.maySendFeatureAbortCommand(message, Constants.ABORT_NOT_IN_CORRECT_MODE);
}
return true;
|
protected boolean | handleVendorCommandWithId(HdmiCecMessage message)
byte[] params = message.getParams();
int vendorId = HdmiUtils.threeBytesToInt(params);
if (vendorId == mService.getVendorId()) {
if (!mService.invokeVendorCommandListenersOnReceived(mDeviceType, message.getSource(),
message.getDestination(), params, true)) {
mService.maySendFeatureAbortCommand(message, Constants.ABORT_NOT_IN_CORRECT_MODE);
}
} else if (message.getDestination() != Constants.ADDR_BROADCAST &&
message.getSource() != Constants.ADDR_UNREGISTERED) {
Slog.v(TAG, "Wrong direct vendor command. Replying with <Feature Abort>");
mService.maySendFeatureAbortCommand(message, Constants.ABORT_UNRECOGNIZED_OPCODE);
} else {
Slog.v(TAG, "Wrong broadcast vendor command. Ignoring");
}
return true;
|
boolean | hasAction(java.lang.Class clazz)
assertRunOnServiceThread();
for (HdmiCecFeatureAction action : mActions) {
if (action.getClass().equals(clazz)) {
return true;
}
}
return false;
|
void | init()
assertRunOnServiceThread();
mPreferredAddress = getPreferredAddress();
|
static void | injectKeyEvent(long time, int action, int keycode, int repeat)
KeyEvent keyEvent = KeyEvent.obtain(time, time, action, keycode,
repeat, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM,
InputDevice.SOURCE_HDMI, null);
InputManager.getInstance().injectInputEvent(keyEvent,
InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
keyEvent.recycle();
|
boolean | isAddressOf(int addr)
assertRunOnServiceThread();
return addr == mAddress;
|
final boolean | isConnectedToArcPort(int path)
assertRunOnServiceThread();
return mService.isConnectedToArcPort(path);
|
protected boolean | isInputReady(int deviceId)Returns true if the TV input associated with the CEC device is ready
to accept further processing such as input switching. This is used
to buffer certain CEC commands and process it later if the input is not
ready yet. For other types of local devices(non-TV), this method returns
true by default to let the commands be processed right away.
return true;
|
static boolean | isPowerOffOrToggleCommand(HdmiCecMessage message)
byte[] params = message.getParams();
return message.getOpcode() == Constants.MESSAGE_USER_CONTROL_PRESSED
&& (params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER
|| params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER_OFF_FUNCTION
|| params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER_TOGGLE_FUNCTION);
|
static boolean | isPowerOnOrToggleCommand(HdmiCecMessage message)
byte[] params = message.getParams();
return message.getOpcode() == Constants.MESSAGE_USER_CONTROL_PRESSED
&& (params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER
|| params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER_ON_FUNCTION
|| params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER_TOGGLE_FUNCTION);
|
protected abstract void | onAddressAllocated(int logicalAddress, int reason)Called once a logical address of the local device is allocated.
|
void | onHotplug(int portId, boolean connected)Called when a hot-plug event issued.
|
protected final boolean | onMessage(HdmiCecMessage message)
assertRunOnServiceThread();
if (dispatchMessageToAction(message)) {
return true;
}
switch (message.getOpcode()) {
case Constants.MESSAGE_ACTIVE_SOURCE:
return handleActiveSource(message);
case Constants.MESSAGE_INACTIVE_SOURCE:
return handleInactiveSource(message);
case Constants.MESSAGE_REQUEST_ACTIVE_SOURCE:
return handleRequestActiveSource(message);
case Constants.MESSAGE_GET_MENU_LANGUAGE:
return handleGetMenuLanguage(message);
case Constants.MESSAGE_GIVE_PHYSICAL_ADDRESS:
return handleGivePhysicalAddress();
case Constants.MESSAGE_GIVE_OSD_NAME:
return handleGiveOsdName(message);
case Constants.MESSAGE_GIVE_DEVICE_VENDOR_ID:
return handleGiveDeviceVendorId();
case Constants.MESSAGE_GET_CEC_VERSION:
return handleGetCecVersion(message);
case Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS:
return handleReportPhysicalAddress(message);
case Constants.MESSAGE_ROUTING_CHANGE:
return handleRoutingChange(message);
case Constants.MESSAGE_ROUTING_INFORMATION:
return handleRoutingInformation(message);
case Constants.MESSAGE_INITIATE_ARC:
return handleInitiateArc(message);
case Constants.MESSAGE_TERMINATE_ARC:
return handleTerminateArc(message);
case Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE:
return handleSetSystemAudioMode(message);
case Constants.MESSAGE_SYSTEM_AUDIO_MODE_STATUS:
return handleSystemAudioModeStatus(message);
case Constants.MESSAGE_REPORT_AUDIO_STATUS:
return handleReportAudioStatus(message);
case Constants.MESSAGE_STANDBY:
return handleStandby(message);
case Constants.MESSAGE_TEXT_VIEW_ON:
return handleTextViewOn(message);
case Constants.MESSAGE_IMAGE_VIEW_ON:
return handleImageViewOn(message);
case Constants.MESSAGE_USER_CONTROL_PRESSED:
return handleUserControlPressed(message);
case Constants.MESSAGE_USER_CONTROL_RELEASED:
return handleUserControlReleased();
case Constants.MESSAGE_SET_STREAM_PATH:
return handleSetStreamPath(message);
case Constants.MESSAGE_GIVE_DEVICE_POWER_STATUS:
return handleGiveDevicePowerStatus(message);
case Constants.MESSAGE_MENU_REQUEST:
return handleMenuRequest(message);
case Constants.MESSAGE_MENU_STATUS:
return handleMenuStatus(message);
case Constants.MESSAGE_VENDOR_COMMAND:
return handleVendorCommand(message);
case Constants.MESSAGE_VENDOR_COMMAND_WITH_ID:
return handleVendorCommandWithId(message);
case Constants.MESSAGE_SET_OSD_NAME:
return handleSetOsdName(message);
case Constants.MESSAGE_RECORD_TV_SCREEN:
return handleRecordTvScreen(message);
case Constants.MESSAGE_TIMER_CLEARED_STATUS:
return handleTimerClearedStatus(message);
case Constants.MESSAGE_REPORT_POWER_STATUS:
return handleReportPowerStatus(message);
case Constants.MESSAGE_TIMER_STATUS:
return handleTimerStatus(message);
case Constants.MESSAGE_RECORD_STATUS:
return handleRecordStatus(message);
default:
return false;
}
|
protected void | onStandby(boolean initiatedByCec)Called when the system goes to standby mode.
|
int | pathToPortId(int newPath)
assertRunOnServiceThread();
return mService.pathToPortId(newPath);
|
void | removeAction(HdmiCecFeatureAction action)Remove the given {@link HdmiCecFeatureAction} object from the action queue.
assertRunOnServiceThread();
action.finish(false);
mActions.remove(action);
checkIfPendingActionsCleared();
|
void | removeAction(java.lang.Class clazz)
assertRunOnServiceThread();
removeActionExcept(clazz, null);
|
void | removeActionExcept(java.lang.Class clazz, HdmiCecFeatureAction exception)
assertRunOnServiceThread();
Iterator<HdmiCecFeatureAction> iter = mActions.iterator();
while (iter.hasNext()) {
HdmiCecFeatureAction action = iter.next();
if (action != exception && action.getClass().equals(clazz)) {
action.finish(false);
iter.remove();
}
}
checkIfPendingActionsCleared();
|
protected void | sendKeyEvent(int keyCode, boolean isPressed)Send a key event to other device.
Slog.w(TAG, "sendKeyEvent not implemented");
|
protected void | sendStandby(int deviceId)
// Do nothing.
|
void | sendUserControlPressedAndReleased(int targetAddress, int cecKeycode)
mService.sendCecCommand(HdmiCecMessageBuilder.buildUserControlPressed(
mAddress, targetAddress, cecKeycode));
mService.sendCecCommand(HdmiCecMessageBuilder.buildUserControlReleased(
mAddress, targetAddress));
|
void | setActivePath(int path)
synchronized (mLock) {
mActiveRoutingPath = path;
}
mService.setActivePortId(pathToPortId(path));
|
void | setActivePortId(int portId)Update the active port.
// We update active routing path instead, since we get the active port id from
// the active routing path.
setActivePath(mService.portIdToPath(portId));
|
void | setActiveSource(com.android.server.hdmi.HdmiCecLocalDevice$ActiveSource newActive)
setActiveSource(newActive.logicalAddress, newActive.physicalAddress);
|
void | setActiveSource(android.hardware.hdmi.HdmiDeviceInfo info)
setActiveSource(info.getLogicalAddress(), info.getPhysicalAddress());
|
void | setActiveSource(int logicalAddress, int physicalAddress)
synchronized (mLock) {
mActiveSource.logicalAddress = logicalAddress;
mActiveSource.physicalAddress = physicalAddress;
}
mService.setLastInputForMhl(Constants.INVALID_PORT_ID);
|
void | setDeviceInfo(android.hardware.hdmi.HdmiDeviceInfo info)
assertRunOnServiceThread();
mDeviceInfo = info;
|
protected abstract void | setPreferredAddress(int addr)Set the preferred logical address to system properties.
|
void | startQueuedActions()
assertRunOnServiceThread();
for (HdmiCecFeatureAction action : mActions) {
if (!action.started()) {
Slog.i(TAG, "Starting queued action:" + action);
action.start();
}
}
|