10340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim/* 20340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim * Copyright (C) 2014 The Android Open Source Project 30340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim * 40340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim * Licensed under the Apache License, Version 2.0 (the "License"); 50340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim * you may not use this file except in compliance with the License. 60340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim * You may obtain a copy of the License at 70340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim * 80340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim * http://www.apache.org/licenses/LICENSE-2.0 90340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim * 100340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim * Unless required by applicable law or agreed to in writing, software 110340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim * distributed under the License is distributed on an "AS IS" BASIS, 120340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim * See the License for the specific language governing permissions and 140340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim * limitations under the License. 150340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim */ 160340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim 170340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kimpackage com.android.server.hdmi; 180340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim 1960cffce420db4c3395f86d3b9bb36003adf26f5dJungshik Jangimport android.annotation.Nullable; 2061f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jangimport android.hardware.hdmi.HdmiDeviceInfo; 21c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kimimport android.hardware.hdmi.HdmiControlManager; 2260cffce420db4c3395f86d3b9bb36003adf26f5dJungshik Jangimport android.hardware.hdmi.IHdmiControlCallback; 230340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kimimport android.os.RemoteException; 240340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kimimport android.util.Slog; 250340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim 260340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kimimport com.android.server.hdmi.HdmiControlService.SendMessageCallback; 270340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim 280340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim/** 290340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim * Feature action for routing control. Exchanges routing-related commands with other devices 300340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim * to determine the new active source. 310340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim * 320340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim * <p>This action is initiated by various cases: 330340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim * <ul> 340340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim * <li> Manual TV input switching 350340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim * <li> Routing change of a CEC switch other than TV 360340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim * <li> New CEC device at the tail of the active routing path 370340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim * <li> Removed CEC device from the active routing path 380340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim * <li> Routing at CEC enable time 390340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim * </ul> 400340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim */ 41b509c2ecd99619248b7a07fb0fa978bb27f25cc3Jungshik Jangfinal class RoutingControlAction extends HdmiCecFeatureAction { 420340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim private static final String TAG = "RoutingControlAction"; 430340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim 440340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim // State in which we wait for <Routing Information> to arrive. If timed out, we use the 450340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim // latest routing path to set the new active source. 4604fd28046acc2ac74339ed94cec76a0bfda846f7Jinsuk Kim private static final int STATE_WAIT_FOR_ROUTING_INFORMATION = 1; 470340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim 480340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim // State in which we wait for <Report Power Status> in response to <Give Device Power Status> 490340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim // we have sent. If the response tells us the device power is on, we send <Set Stream Path> 500340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim // to make it the active source. Otherwise we do not send <Set Stream Path>, and possibly 510340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim // just show the blank screen. 5204fd28046acc2ac74339ed94cec76a0bfda846f7Jinsuk Kim private static final int STATE_WAIT_FOR_REPORT_POWER_STATUS = 2; 530340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim 540340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim // Time out in millseconds used for <Routing Information> 550340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim private static final int TIMEOUT_ROUTING_INFORMATION_MS = 1000; 560340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim 570340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim // Time out in milliseconds used for <Report Power Status> 580340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim private static final int TIMEOUT_REPORT_POWER_STATUS_MS = 1000; 590340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim 6004fd28046acc2ac74339ed94cec76a0bfda846f7Jinsuk Kim // true if <Give Power Status> should be sent once the new active routing path is determined. 6104fd28046acc2ac74339ed94cec76a0bfda846f7Jinsuk Kim private final boolean mQueryDevicePowerStatus; 6204fd28046acc2ac74339ed94cec76a0bfda846f7Jinsuk Kim 6372b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim // If set to true, call {@link HdmiControlService#invokeInputChangeListener()} when 6472b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim // the routing control/active source change happens. The listener should be called if 6572b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim // the events are triggered by external events such as manual switch port change or incoming 6672b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim // <Inactive Source> command. 6772b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim private final boolean mNotifyInputChange; 6872b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim 6960cffce420db4c3395f86d3b9bb36003adf26f5dJungshik Jang @Nullable private final IHdmiControlCallback mCallback; 700340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim 710340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim // The latest routing path. Updated by each <Routing Information> from CEC switches. 720340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim private int mCurrentRoutingPath; 730340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim 7404fd28046acc2ac74339ed94cec76a0bfda846f7Jinsuk Kim RoutingControlAction(HdmiCecLocalDevice localDevice, int path, boolean queryDevicePowerStatus, 7504fd28046acc2ac74339ed94cec76a0bfda846f7Jinsuk Kim IHdmiControlCallback callback) { 7679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang super(localDevice); 770340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim mCallback = callback; 78401e3de791c0e2a4348361fbd560da9530156e22Jinsuk Kim mCurrentRoutingPath = path; 7904fd28046acc2ac74339ed94cec76a0bfda846f7Jinsuk Kim mQueryDevicePowerStatus = queryDevicePowerStatus; 8072b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim // Callback is non-null when routing control action is brought up by binder API. Use 8172b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim // this as an indicator for the input change notification. These API calls will get 8272b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim // the result through this callback, not through notification. Any other events that 8372b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim // trigger the routing control is external, for which notifcation is used. 8472b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim mNotifyInputChange = (callback == null); 850340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim } 860340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim 870340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim @Override 880340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim public boolean start() { 890340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim mState = STATE_WAIT_FOR_ROUTING_INFORMATION; 900340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim addTimer(mState, TIMEOUT_ROUTING_INFORMATION_MS); 910340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim return true; 920340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim } 930340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim 940340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim @Override 950340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim public boolean processCommand(HdmiCecMessage cmd) { 960340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim int opcode = cmd.getOpcode(); 970340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim byte[] params = cmd.getParams(); 980340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim if (mState == STATE_WAIT_FOR_ROUTING_INFORMATION 99c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim && opcode == Constants.MESSAGE_ROUTING_INFORMATION) { 1000340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim // Keep updating the physicalAddress as we receive <Routing Information>. 1010340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim // If the routing path doesn't belong to the currently active one, we should 102401e3de791c0e2a4348361fbd560da9530156e22Jinsuk Kim // ignore it since it might have come from other routing change sequence. 1030340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim int routingPath = HdmiUtils.twoBytesToInt(params); 1047c3a95633d307c4be30c9dbbf1071063aa7a3c64Jinsuk Kim if (!HdmiUtils.isInActiveRoutingPath(mCurrentRoutingPath, routingPath)) { 1050340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim return true; 1060340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim } 1070340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim mCurrentRoutingPath = routingPath; 1080340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim // Stop possible previous routing change sequence if in progress. 1097c3a95633d307c4be30c9dbbf1071063aa7a3c64Jinsuk Kim removeActionExcept(RoutingControlAction.class, this); 1100340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim addTimer(mState, TIMEOUT_ROUTING_INFORMATION_MS); 1110340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim return true; 1120340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim } else if (mState == STATE_WAIT_FOR_REPORT_POWER_STATUS 113c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim && opcode == Constants.MESSAGE_REPORT_POWER_STATUS) { 1140340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim handleReportPowerStatus(cmd.getParams()[0]); 1150340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim return true; 1160340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim } 1170340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim return false; 1180340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim } 1190340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim 1200340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim private void handleReportPowerStatus(int devicePowerStatus) { 121cae6627702a3bae3121f0ebbb9c8069e77f81cc7Jinsuk Kim if (isPowerOnOrTransient(getTvPowerStatus())) { 122337ce19bef8be8edf6102aa31eb349772b622a8dJinsuk Kim tv().updateActiveInput(mCurrentRoutingPath, mNotifyInputChange); 123cae6627702a3bae3121f0ebbb9c8069e77f81cc7Jinsuk Kim if (isPowerOnOrTransient(devicePowerStatus)) { 1240340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim sendSetStreamPath(); 1250340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim } 12692b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim } 127dd233f3d25386ecd2ddb1b48c58f2a84e11f4286Jinsuk Kim finishWithCallback(HdmiControlManager.RESULT_SUCCESS); 128dd233f3d25386ecd2ddb1b48c58f2a84e11f4286Jinsuk Kim } 1290340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim 1300340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim private int getTvPowerStatus() { 131cae6627702a3bae3121f0ebbb9c8069e77f81cc7Jinsuk Kim return tv().getPowerStatus(); 1320340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim } 1330340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim 134cae6627702a3bae3121f0ebbb9c8069e77f81cc7Jinsuk Kim private static boolean isPowerOnOrTransient(int status) { 135c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim return status == HdmiControlManager.POWER_STATUS_ON 136c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim || status == HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON; 1370340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim } 1380340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim 1390340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim private void sendSetStreamPath() { 14079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang sendCommand(HdmiCecMessageBuilder.buildSetStreamPath(getSourceAddress(), 14179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mCurrentRoutingPath)); 1420340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim } 1430340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim 144dd233f3d25386ecd2ddb1b48c58f2a84e11f4286Jinsuk Kim private void finishWithCallback(int result) { 145dd233f3d25386ecd2ddb1b48c58f2a84e11f4286Jinsuk Kim invokeCallback(result); 146dd233f3d25386ecd2ddb1b48c58f2a84e11f4286Jinsuk Kim finish(); 147dd233f3d25386ecd2ddb1b48c58f2a84e11f4286Jinsuk Kim } 148dd233f3d25386ecd2ddb1b48c58f2a84e11f4286Jinsuk Kim 1490340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim @Override 1500340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim public void handleTimerEvent(int timeoutState) { 1510340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim if (mState != timeoutState || mState == STATE_NONE) { 1520340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim Slog.w("CEC", "Timer in a wrong state. Ignored."); 1530340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim return; 1540340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim } 1550340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim switch (timeoutState) { 1560340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim case STATE_WAIT_FOR_ROUTING_INFORMATION: 15761f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang HdmiDeviceInfo device = tv().getDeviceInfoByPath(mCurrentRoutingPath); 15804fd28046acc2ac74339ed94cec76a0bfda846f7Jinsuk Kim if (device != null && mQueryDevicePowerStatus) { 1590340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim int deviceLogicalAddress = device.getLogicalAddress(); 1600340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim queryDevicePowerStatus(deviceLogicalAddress, new SendMessageCallback() { 1610340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim @Override 1620340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim public void onSendCompleted(int error) { 163c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim handlDevicePowerStatusAckResult( 164c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim error == HdmiControlManager.RESULT_SUCCESS); 1650340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim } 1660340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim }); 16704fd28046acc2ac74339ed94cec76a0bfda846f7Jinsuk Kim } else { 16872b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim tv().updateActiveInput(mCurrentRoutingPath, mNotifyInputChange); 169dd233f3d25386ecd2ddb1b48c58f2a84e11f4286Jinsuk Kim finishWithCallback(HdmiControlManager.RESULT_SUCCESS); 1700340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim } 1710340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim return; 1720340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim case STATE_WAIT_FOR_REPORT_POWER_STATUS: 173cae6627702a3bae3121f0ebbb9c8069e77f81cc7Jinsuk Kim if (isPowerOnOrTransient(getTvPowerStatus())) { 17472b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim tv().updateActiveInput(mCurrentRoutingPath, mNotifyInputChange); 17592b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim sendSetStreamPath(); 1760340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim } 177dd233f3d25386ecd2ddb1b48c58f2a84e11f4286Jinsuk Kim finishWithCallback(HdmiControlManager.RESULT_SUCCESS); 1780340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim return; 1790340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim } 1800340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim } 1810340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim 1820340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim private void queryDevicePowerStatus(int address, SendMessageCallback callback) { 18379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang sendCommand(HdmiCecMessageBuilder.buildGiveDevicePowerStatus(getSourceAddress(), address), 1840340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim callback); 1850340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim } 1860340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim 1870340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim private void handlDevicePowerStatusAckResult(boolean acked) { 1880340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim if (acked) { 1890340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim mState = STATE_WAIT_FOR_REPORT_POWER_STATUS; 1900340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim addTimer(mState, TIMEOUT_REPORT_POWER_STATUS_MS); 1910340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim } else { 19272b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim tv().updateActiveInput(mCurrentRoutingPath, mNotifyInputChange); 19392b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim sendSetStreamPath(); 194dd233f3d25386ecd2ddb1b48c58f2a84e11f4286Jinsuk Kim finishWithCallback(HdmiControlManager.RESULT_SUCCESS); 1950340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim } 1960340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim } 1970340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim 1980340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim private void invokeCallback(int result) { 1990340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim if (mCallback == null) { 2000340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim return; 2010340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim } 2020340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim try { 2030340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim mCallback.onComplete(result); 2040340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim } catch (RemoteException e) { 2050340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim // Do nothing. 2060340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim } 2070340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim } 2080340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim} 209