一,tvsource DroidLogicTv.java
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (!isBootvideoStopped())
return true;
sendKeyEventToHdmi(event.getKeyCode(), event.getAction() == KeyEvent.ACTION_DOWN);
if (isMediaKeyEvent(event))//if it's media key, TV don't process it.
return true;
boolean ret = processKeyEvent(event.getKeyCode(), event);
return ret ? ret : super.dispatchKeyEvent(event);
}
private void sendKeyEventToHdmi(int keyCode, boolean isPressed) {
if (mHdmiTvClient != null) {
mHdmiTvClient.sendKeyEvent(keyCode, isPressed);
}
}
二,HdmiCecLocalDeviceTv.java
@Override
@ServiceThreadOnly
protected void sendKeyEvent(int keyCode, boolean isPressed) {
assertRunOnServiceThread();
if (!HdmiCecKeycode.isSupportedKeycode(keyCode)) {
Slog.w(TAG, "Unsupported key: " + keyCode);
return;
}
if (mSelectAddr == Constants.ADDR_INVALID) {
Slog.w(TAG, "Discard key event due to no device is selected");
return ;
}
List<SendKeyAction> action = getActions(SendKeyAction.class);
int logicalAddress = findKeyReceiverAddress();
if (logicalAddress == mAddress) {
Slog.w(TAG, "Discard key event to itself :" + keyCode + " pressed:" + isPressed);
return;
}
if (!action.isEmpty()) {
action.get(0).processKeyEvent(keyCode, isPressed);
} else {
if (isPressed) {
if (logicalAddress != Constants.ADDR_INVALID) {
addAndStartAction(new SendKeyAction(this, logicalAddress, keyCode));
return;
}
}
Slog.w(TAG, "Discard key event: " + keyCode + " pressed:" + isPressed);
}
}
三 SendKeyAction.java
public boolean start() {
sendKeyDown(mLastKeycode);
mLastSendKeyTime = getCurrentTime();
// finish action for non-repeatable key.
if (!HdmiCecKeycode.isRepeatableKey(mLastKeycode)) {
sendKeyUp();
finish();
return true;
}
mState = STATE_CHECKING_LONGPRESS;
addTimer(mState, AWAIT_LONGPRESS_MS);
return true;
}
private void sendKeyDown(int keycode) {
byte[] cecKeycodeAndParams = HdmiCecKeycode.androidKeyToCecKey(keycode);
if (cecKeycodeAndParams == null) {
return;
}
sendCommand(HdmiCecMessageBuilder.buildUserControlPressed(getSourceAddress(),
mTargetAddress, cecKeycodeAndParams));
}
四 HdmiControlService.java
@ServiceThreadOnly
void sendCecCommand(HdmiCecMessage command, @Nullable SendMessageCallback callback) {
assertRunOnServiceThread();
if (mMessageValidator.isValid(command) == HdmiCecMessageValidator.OK) {
mCecController.sendCommand(command, callback);
} else {
HdmiLogger.error("Invalid message type:" + command);
if (callback != null) {
callback.onSendCompleted(Constants.SEND_RESULT_FAILURE);
}
}
}
五 HdmiCecController.java
@ServiceThreadOnly
void sendCommand(final HdmiCecMessage cecMessage,
final HdmiControlService.SendMessageCallback callback) {
assertRunOnServiceThread();
runOnIoThread(new Runnable() {
@Override
public void run() {
HdmiLogger.debug("[S]:" + cecMessage);
byte[] body = buildBody(cecMessage.getOpcode(), cecMessage.getParams());
int i = 0;
int errorCode = Constants.SEND_RESULT_SUCCESS;
do {
errorCode = nativeSendCecCommand(mNativePtr, cecMessage.getSource(),
cecMessage.getDestination(), body);
if (errorCode == Constants.SEND_RESULT_SUCCESS) {
break;
}
} while (i++ < HdmiConfig.RETRANSMISSION_COUNT);
final int finalError = errorCode;
if (finalError != Constants.SEND_RESULT_SUCCESS) {
Slog.w(TAG, "Failed to send " + cecMessage);
}
/* added by wj, remove device if not ack */
if (finalError == Constants.SEND_RESULT_NAK) {
if (mHasChild && !