HdmiCecLocalDevice.java revision 25c20298ad04e0e591e0cfdc0bb9d01a985433ab
12918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim/* 22918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim * Copyright (C) 2014 The Android Open Source Project 32918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim * 42918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim * Licensed under the Apache License, Version 2.0 (the "License"); 52918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim * you may not use this file except in compliance with the License. 62918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim * You may obtain a copy of the License at 72918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim * 82918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim * http://www.apache.org/licenses/LICENSE-2.0 92918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim * 102918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim * Unless required by applicable law or agreed to in writing, software 112918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim * distributed under the License is distributed on an "AS IS" BASIS, 122918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim * See the License for the specific language governing permissions and 142918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim * limitations under the License. 152918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim */ 162918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim 172918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kimpackage com.android.server.hdmi; 182918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim 191a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jangimport android.hardware.hdmi.HdmiCecDeviceInfo; 204fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jangimport android.os.Handler; 2179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jangimport android.os.Looper; 224fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jangimport android.os.Message; 23092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jangimport android.util.Slog; 242918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim 2579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jangimport com.android.internal.annotations.GuardedBy; 26a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jangimport com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly; 2779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 2879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jangimport java.util.ArrayList; 2943c23e273e1b78caf26899eca5a4f51df9d52400Jinsuk Kimimport java.util.Collections; 3079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jangimport java.util.Iterator; 3179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jangimport java.util.LinkedList; 3279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jangimport java.util.List; 3379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 342918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim/** 352918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim * Class that models a logical CEC device hosted in this system. Handles initialization, 362918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim * CEC commands that call for actions customized per device type. 372918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim */ 382918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kimabstract class HdmiCecLocalDevice { 39092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang private static final String TAG = "HdmiCecLocalDevice"; 402918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim 414fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang private static final int MSG_DISABLE_DEVICE_TIMEOUT = 1; 424fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang // Timeout in millisecond for device clean up (5s). 434fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang // Normal actions timeout is 2s but some of them would have several sequence of timeout. 444fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang private static final int DEVICE_CLEANUP_TIMEOUT = 5000; 454fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang 463ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang protected final HdmiControlService mService; 472918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim protected final int mDeviceType; 482918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim protected int mAddress; 492918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim protected int mPreferredAddress; 501a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang protected HdmiCecDeviceInfo mDeviceInfo; 512918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim 5272b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim static class ActiveSource { 5372b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim int logicalAddress; 5472b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim int physicalAddress; 5572b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim 5643c23e273e1b78caf26899eca5a4f51df9d52400Jinsuk Kim public ActiveSource() { 5743c23e273e1b78caf26899eca5a4f51df9d52400Jinsuk Kim invalidate(); 5843c23e273e1b78caf26899eca5a4f51df9d52400Jinsuk Kim } 5972b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim public ActiveSource(int logical, int physical) { 6072b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim logicalAddress = logical; 6172b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim physicalAddress = physical; 6272b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim } 6372b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim public static ActiveSource of(int logical, int physical) { 6472b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim return new ActiveSource(logical, physical); 6572b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim } 6672b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim public boolean isValid() { 6772b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim return HdmiUtils.isValidAddress(logicalAddress); 6872b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim } 6943c23e273e1b78caf26899eca5a4f51df9d52400Jinsuk Kim public void invalidate() { 7043c23e273e1b78caf26899eca5a4f51df9d52400Jinsuk Kim logicalAddress = Constants.ADDR_INVALID; 7143c23e273e1b78caf26899eca5a4f51df9d52400Jinsuk Kim physicalAddress = Constants.INVALID_PHYSICAL_ADDRESS; 7243c23e273e1b78caf26899eca5a4f51df9d52400Jinsuk Kim } 7372b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim public boolean equals(int logical, int physical) { 7472b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim return logicalAddress == logical && physicalAddress == physical; 7572b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim } 7672b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim @Override 7772b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim public boolean equals(Object obj) { 7872b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim if (obj instanceof ActiveSource) { 7972b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim ActiveSource that = (ActiveSource) obj; 8072b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim return that.logicalAddress == logicalAddress && 8172b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim that.physicalAddress == physicalAddress; 8272b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim } 8372b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim return false; 8472b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim } 8572b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim @Override 8672b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim public int hashCode() { 8772b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim return logicalAddress * 29 + physicalAddress; 8872b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim } 8972b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim } 9079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // Logical address of the active source. 9179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang @GuardedBy("mLock") 9243c23e273e1b78caf26899eca5a4f51df9d52400Jinsuk Kim protected final ActiveSource mActiveSource = new ActiveSource(); 9379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 9479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // Active routing path. Physical address of the active source but not all the time, such as 9579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // when the new active source does not claim itself to be one. Note that we don't keep 9679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // the active port id (or active input) since it can be gotten by {@link #pathToPortId(int)}. 9779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang @GuardedBy("mLock") 9879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang private int mActiveRoutingPath; 9979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 10079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected final HdmiCecMessageCache mCecMessageCache = new HdmiCecMessageCache(); 10179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected final Object mLock; 10279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 10379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // A collection of FeatureAction. 10479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // Note that access to this collection should happen in service thread. 10579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang private final LinkedList<FeatureAction> mActions = new LinkedList<>(); 10679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 107c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo private final Handler mHandler = new Handler () { 1084fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang @Override 1094fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang public void handleMessage(Message msg) { 1104fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang switch (msg.what) { 1114fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang case MSG_DISABLE_DEVICE_TIMEOUT: 1124fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang handleDisableDeviceTimeout(); 1134fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang break; 1144fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang } 1154fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang } 1164fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang }; 1174fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang 1184fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang /** 1194fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang * A callback interface to get notified when all pending action is cleared. 1204fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang * It can be called when timeout happened. 1214fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang */ 1224fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang interface PendingActionClearedCallback { 1234fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang void onCleared(HdmiCecLocalDevice device); 1244fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang } 1254fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang 1264fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang protected PendingActionClearedCallback mPendingActionClearedCallback; 1274fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang 1283ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang protected HdmiCecLocalDevice(HdmiControlService service, int deviceType) { 1293ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang mService = service; 1302918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim mDeviceType = deviceType; 131c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim mAddress = Constants.ADDR_UNREGISTERED; 13279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mLock = service.getServiceLock(); 1332918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim } 1342918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim 1352918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim // Factory method that returns HdmiCecLocalDevice of corresponding type. 1363ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang static HdmiCecLocalDevice create(HdmiControlService service, int deviceType) { 1372918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim switch (deviceType) { 138c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case HdmiCecDeviceInfo.DEVICE_TV: 1393ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang return new HdmiCecLocalDeviceTv(service); 140c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case HdmiCecDeviceInfo.DEVICE_PLAYBACK: 1413ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang return new HdmiCecLocalDevicePlayback(service); 1422918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim default: 1432918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim return null; 1442918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim } 1452918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim } 1462918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim 147a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 1483ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang void init() { 149a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang assertRunOnServiceThread(); 150af2acf0447aff34450cde2bcfb35dff9cf631729Jinsuk Kim mPreferredAddress = getPreferredAddress(); 1513ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang } 1522918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim 1538b308d93c8fdcc7304b33d9b445ae3807eae97c8Jungshik Jang /** 1543ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang * Called once a logical address of the local device is allocated. 1558b308d93c8fdcc7304b33d9b445ae3807eae97c8Jungshik Jang */ 156a9f10629f4bc1a82761917645ff4d2b6d42e47b3Jungshik Jang protected abstract void onAddressAllocated(int logicalAddress, boolean fromBootup); 1578b308d93c8fdcc7304b33d9b445ae3807eae97c8Jungshik Jang 158092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang /** 159af2acf0447aff34450cde2bcfb35dff9cf631729Jinsuk Kim * Get the preferred logical address from system properties. 160af2acf0447aff34450cde2bcfb35dff9cf631729Jinsuk Kim */ 161af2acf0447aff34450cde2bcfb35dff9cf631729Jinsuk Kim protected abstract int getPreferredAddress(); 162af2acf0447aff34450cde2bcfb35dff9cf631729Jinsuk Kim 163af2acf0447aff34450cde2bcfb35dff9cf631729Jinsuk Kim /** 164af2acf0447aff34450cde2bcfb35dff9cf631729Jinsuk Kim * Set the preferred logical address to system properties. 165af2acf0447aff34450cde2bcfb35dff9cf631729Jinsuk Kim */ 166af2acf0447aff34450cde2bcfb35dff9cf631729Jinsuk Kim protected abstract void setPreferredAddress(int addr); 167af2acf0447aff34450cde2bcfb35dff9cf631729Jinsuk Kim 168af2acf0447aff34450cde2bcfb35dff9cf631729Jinsuk Kim /** 169092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang * Dispatch incoming message. 170092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang * 171092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang * @param message incoming message 172092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang * @return true if consumed a message; otherwise, return false. 173092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang */ 174a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 17525c20298ad04e0e591e0cfdc0bb9d01a985433abYuncheol Heo boolean dispatchMessage(HdmiCecMessage message) { 17679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 177092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang int dest = message.getDestination(); 178c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim if (dest != mAddress && dest != Constants.ADDR_BROADCAST) { 179092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return false; 180092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 18179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // Cache incoming message. Note that it caches only white-listed one. 18279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mCecMessageCache.cacheMessage(message); 183092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return onMessage(message); 184092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 185092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang 186a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 18760cffce420db4c3395f86d3b9bb36003adf26f5dJungshik Jang protected final boolean onMessage(HdmiCecMessage message) { 18879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 18979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang if (dispatchMessageToAction(message)) { 19079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return true; 19179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 192092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang switch (message.getOpcode()) { 193c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_ACTIVE_SOURCE: 1948333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim return handleActiveSource(message); 195c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_INACTIVE_SOURCE: 1968333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim return handleInactiveSource(message); 197c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_REQUEST_ACTIVE_SOURCE: 1988333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim return handleRequestActiveSource(message); 199c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_GET_MENU_LANGUAGE: 200092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return handleGetMenuLanguage(message); 201c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_GIVE_PHYSICAL_ADDRESS: 202092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return handleGivePhysicalAddress(); 203c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_GIVE_OSD_NAME: 204092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return handleGiveOsdName(message); 205c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_GIVE_DEVICE_VENDOR_ID: 206092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return handleGiveDeviceVendorId(); 207c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_GET_CEC_VERSION: 208092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return handleGetCecVersion(message); 209c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS: 21060cffce420db4c3395f86d3b9bb36003adf26f5dJungshik Jang return handleReportPhysicalAddress(message); 211c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_ROUTING_CHANGE: 21292b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim return handleRoutingChange(message); 213c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_INITIATE_ARC: 21479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return handleInitiateArc(message); 215c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_TERMINATE_ARC: 21679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return handleTerminateArc(message); 217c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE: 21879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return handleSetSystemAudioMode(message); 219c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_SYSTEM_AUDIO_MODE_STATUS: 22079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return handleSystemAudioModeStatus(message); 221c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_REPORT_AUDIO_STATUS: 2228fa36b110be29d92a9aba070fa4666eefb14b584Jungshik Jang return handleReportAudioStatus(message); 223c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_STANDBY: 22438db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return handleStandby(message); 225c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_TEXT_VIEW_ON: 22638db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return handleTextViewOn(message); 227c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_IMAGE_VIEW_ON: 22838db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return handleImageViewOn(message); 229c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_USER_CONTROL_PRESSED: 23038db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return handleUserControlPressed(message); 231c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_SET_STREAM_PATH: 23238db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return handleSetStreamPath(message); 233c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_GIVE_DEVICE_POWER_STATUS: 23438db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return handleGiveDevicePowerStatus(message); 235119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim case Constants.MESSAGE_VENDOR_COMMAND: 236119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim return handleVendorCommand(message); 237119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim case Constants.MESSAGE_VENDOR_COMMAND_WITH_ID: 238119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim return handleVendorCommandWithId(message); 2398f2ed357a23fac4a55da43d20138b438b4ac79a7Jungshik Jang case Constants.MESSAGE_SET_OSD_NAME: 2408f2ed357a23fac4a55da43d20138b438b4ac79a7Jungshik Jang return handleSetOsdName(message); 241b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang case Constants.MESSAGE_RECORD_TV_SCREEN: 242b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang return handleRecordTvScreen(message); 243092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang default: 244092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return false; 245092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 246092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 247092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang 248a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 24979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang private boolean dispatchMessageToAction(HdmiCecMessage message) { 250a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang assertRunOnServiceThread(); 25179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang for (FeatureAction action : mActions) { 25279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang if (action.processCommand(message)) { 25379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return true; 25479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 25579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 25679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return false; 25779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 25879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 259a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 260092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang protected boolean handleGivePhysicalAddress() { 26179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 26279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 263092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang int physicalAddress = mService.getPhysicalAddress(); 264092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( 265092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang mAddress, physicalAddress, mDeviceType); 266092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang mService.sendCecCommand(cecMessage); 267092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return true; 268092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 269092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang 270a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 271092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang protected boolean handleGiveDeviceVendorId() { 27279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 273092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang int vendorId = mService.getVendorId(); 274092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildDeviceVendorIdCommand( 275092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang mAddress, vendorId); 276092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang mService.sendCecCommand(cecMessage); 277092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return true; 278092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 279092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang 280a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 281092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang protected boolean handleGetCecVersion(HdmiCecMessage message) { 28279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 283092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang int version = mService.getCecVersion(); 284092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildCecVersion(message.getDestination(), 285092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang message.getSource(), version); 286092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang mService.sendCecCommand(cecMessage); 287092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return true; 288092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 289092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang 290a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 2918333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim protected boolean handleActiveSource(HdmiCecMessage message) { 2928333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim return false; 2938333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim } 2948333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim 2958333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim @ServiceThreadOnly 2968333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim protected boolean handleInactiveSource(HdmiCecMessage message) { 2978333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim return false; 2988333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim } 2998333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim 3008333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim @ServiceThreadOnly 3018333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim protected boolean handleRequestActiveSource(HdmiCecMessage message) { 3028333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim return false; 3038333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim } 3048333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim 3058333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim @ServiceThreadOnly 306092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang protected boolean handleGetMenuLanguage(HdmiCecMessage message) { 30779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 308092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang Slog.w(TAG, "Only TV can handle <Get Menu Language>:" + message.toString()); 309092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang mService.sendCecCommand( 310092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang HdmiCecMessageBuilder.buildFeatureAbortCommand(mAddress, 311c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim message.getSource(), Constants.MESSAGE_GET_MENU_LANGUAGE, 31225c20298ad04e0e591e0cfdc0bb9d01a985433abYuncheol Heo Constants.ABORT_UNRECOGNIZED_OPCODE)); 313092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return true; 314092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 315092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang 316a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 317092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang protected boolean handleGiveOsdName(HdmiCecMessage message) { 31879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 319092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang // Note that since this method is called after logical address allocation is done, 320092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang // mDeviceInfo should not be null. 321092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildSetOsdNameCommand( 322092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang mAddress, message.getSource(), mDeviceInfo.getDisplayName()); 323092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang if (cecMessage != null) { 324092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang mService.sendCecCommand(cecMessage); 325092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } else { 326092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang Slog.w(TAG, "Failed to build <Get Osd Name>:" + mDeviceInfo.getDisplayName()); 327092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 328092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return true; 329092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 330092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang 33192b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim protected boolean handleRoutingChange(HdmiCecMessage message) { 33292b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim return false; 33392b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim } 33492b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim 33560cffce420db4c3395f86d3b9bb36003adf26f5dJungshik Jang protected boolean handleReportPhysicalAddress(HdmiCecMessage message) { 33660cffce420db4c3395f86d3b9bb36003adf26f5dJungshik Jang return false; 33760cffce420db4c3395f86d3b9bb36003adf26f5dJungshik Jang } 33860cffce420db4c3395f86d3b9bb36003adf26f5dJungshik Jang 33979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected boolean handleSystemAudioModeStatus(HdmiCecMessage message) { 34079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return false; 34179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 34279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 34379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected boolean handleSetSystemAudioMode(HdmiCecMessage message) { 34479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return false; 34579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 34679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 34779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected boolean handleTerminateArc(HdmiCecMessage message) { 34879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return false; 34979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 35079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 35179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected boolean handleInitiateArc(HdmiCecMessage message) { 35279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return false; 3538fa36b110be29d92a9aba070fa4666eefb14b584Jungshik Jang } 3548fa36b110be29d92a9aba070fa4666eefb14b584Jungshik Jang 3558fa36b110be29d92a9aba070fa4666eefb14b584Jungshik Jang protected boolean handleReportAudioStatus(HdmiCecMessage message) { 3568fa36b110be29d92a9aba070fa4666eefb14b584Jungshik Jang return false; 35779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 35879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 359a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 36038db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo protected boolean handleStandby(HdmiCecMessage message) { 36138db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo assertRunOnServiceThread(); 36238db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo // Seq #12 3634d43d93743222311c6377d4904c19ccb93699d3bJinsuk Kim if (mService.isControlEnabled() && !mService.isProhibitMode() 36438db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo && mService.isPowerOnOrTransient()) { 36538db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo mService.standby(); 36638db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return true; 36738db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo } 36838db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return false; 36938db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo } 37038db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo 37138db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo @ServiceThreadOnly 37238db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo protected boolean handleUserControlPressed(HdmiCecMessage message) { 37338db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo assertRunOnServiceThread(); 37438db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo if (mService.isPowerOnOrTransient() && isPowerOffOrToggleCommand(message)) { 37538db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo mService.standby(); 37638db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return true; 37738db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo } else if (mService.isPowerStandbyOrTransient() && isPowerOnOrToggleCommand(message)) { 37838db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo mService.wakeUp(); 37938db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return true; 38038db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo } 38138db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return false; 38238db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo } 38338db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo 38425c20298ad04e0e591e0cfdc0bb9d01a985433abYuncheol Heo static boolean isPowerOnOrToggleCommand(HdmiCecMessage message) { 38538db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo byte[] params = message.getParams(); 386c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim return message.getOpcode() == Constants.MESSAGE_USER_CONTROL_PRESSED 387210d73df0b77b4c8be67ecc92afb238dc8c7ccfaJungshik Jang && (params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER 388210d73df0b77b4c8be67ecc92afb238dc8c7ccfaJungshik Jang || params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER_ON_FUNCTION 389210d73df0b77b4c8be67ecc92afb238dc8c7ccfaJungshik Jang || params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER_TOGGLE_FUNCTION); 39038db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo } 39138db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo 39225c20298ad04e0e591e0cfdc0bb9d01a985433abYuncheol Heo static boolean isPowerOffOrToggleCommand(HdmiCecMessage message) { 39338db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo byte[] params = message.getParams(); 394c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim return message.getOpcode() == Constants.MESSAGE_USER_CONTROL_PRESSED 395210d73df0b77b4c8be67ecc92afb238dc8c7ccfaJungshik Jang && (params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER 396210d73df0b77b4c8be67ecc92afb238dc8c7ccfaJungshik Jang || params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER_OFF_FUNCTION 397210d73df0b77b4c8be67ecc92afb238dc8c7ccfaJungshik Jang || params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER_TOGGLE_FUNCTION); 39838db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo } 39938db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo 40038db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo protected boolean handleTextViewOn(HdmiCecMessage message) { 40138db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return false; 40238db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo } 40338db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo 40438db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo protected boolean handleImageViewOn(HdmiCecMessage message) { 40538db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return false; 40638db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo } 40738db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo 40838db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo protected boolean handleSetStreamPath(HdmiCecMessage message) { 40938db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return false; 41038db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo } 41138db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo 41238db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo protected boolean handleGiveDevicePowerStatus(HdmiCecMessage message) { 41338db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo mService.sendCecCommand(HdmiCecMessageBuilder.buildReportPowerStatus( 41438db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo mAddress, message.getSource(), mService.getPowerStatus())); 41538db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return true; 41638db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo } 41738db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo 418119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim protected boolean handleVendorCommand(HdmiCecMessage message) { 419119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim mService.invokeVendorCommandListeners(mDeviceType, message.getSource(), 420119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim message.getParams(), false); 421119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim return true; 422119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim } 423119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim 424119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim protected boolean handleVendorCommandWithId(HdmiCecMessage message) { 425119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim byte[] params = message.getParams(); 426119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim int vendorId = HdmiUtils.threeBytesToInt(params); 427119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim if (vendorId == mService.getVendorId()) { 428119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim mService.invokeVendorCommandListeners(mDeviceType, message.getSource(), params, true); 429119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim } else if (message.getDestination() != Constants.ADDR_BROADCAST && 430119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim message.getSource() != Constants.ADDR_UNREGISTERED) { 431119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim Slog.v(TAG, "Wrong direct vendor command. Replying with <Feature Abort>"); 432119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim mService.sendCecCommand(HdmiCecMessageBuilder.buildFeatureAbortCommand(mAddress, 433119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim message.getSource(), Constants.MESSAGE_VENDOR_COMMAND_WITH_ID, 43425c20298ad04e0e591e0cfdc0bb9d01a985433abYuncheol Heo Constants.ABORT_UNRECOGNIZED_OPCODE)); 435119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim } else { 436119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim Slog.v(TAG, "Wrong broadcast vendor command. Ignoring"); 437119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim } 438119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim return true; 439119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim } 440119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim 4418f2ed357a23fac4a55da43d20138b438b4ac79a7Jungshik Jang protected boolean handleSetOsdName(HdmiCecMessage message) { 4428f2ed357a23fac4a55da43d20138b438b4ac79a7Jungshik Jang // The default behavior of <Set Osd Name> is doing nothing. 4438f2ed357a23fac4a55da43d20138b438b4ac79a7Jungshik Jang return true; 4448f2ed357a23fac4a55da43d20138b438b4ac79a7Jungshik Jang } 4458f2ed357a23fac4a55da43d20138b438b4ac79a7Jungshik Jang 446b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang protected boolean handleRecordTvScreen(HdmiCecMessage message) { 44725c20298ad04e0e591e0cfdc0bb9d01a985433abYuncheol Heo // The default behavior of <Record TV Screen> is replying <Feature Abort> with 44825c20298ad04e0e591e0cfdc0bb9d01a985433abYuncheol Heo // "Cannot provide source". 449b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang mService.sendCecCommand(HdmiCecMessageBuilder.buildFeatureAbortCommand(mAddress, 45025c20298ad04e0e591e0cfdc0bb9d01a985433abYuncheol Heo message.getSource(), message.getOpcode(), Constants.ABORT_CANNOT_PROVIDE_SOURCE)); 451b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang return true; 452b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang } 453b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang 45438db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo @ServiceThreadOnly 455a9f10629f4bc1a82761917645ff4d2b6d42e47b3Jungshik Jang final void handleAddressAllocated(int logicalAddress, boolean fromBootup) { 45679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 4573ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang mAddress = mPreferredAddress = logicalAddress; 458a9f10629f4bc1a82761917645ff4d2b6d42e47b3Jungshik Jang onAddressAllocated(logicalAddress, fromBootup); 459af2acf0447aff34450cde2bcfb35dff9cf631729Jinsuk Kim setPreferredAddress(logicalAddress); 4601a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang } 4611a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang 462a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 4631a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang HdmiCecDeviceInfo getDeviceInfo() { 46479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 4651a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang return mDeviceInfo; 4661a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang } 4671a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang 468a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 4691a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang void setDeviceInfo(HdmiCecDeviceInfo info) { 47079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 4711a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang mDeviceInfo = info; 4721a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang } 4731a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang 4742918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim // Returns true if the logical address is same as the argument. 475a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 4762918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim boolean isAddressOf(int addr) { 47779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 4782918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim return addr == mAddress; 4792918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim } 4802918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim 4812918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim // Resets the logical address to unregistered(15), meaning the logical device is invalid. 482a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 4832918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim void clearAddress() { 48479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 485c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim mAddress = Constants.ADDR_UNREGISTERED; 4862918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim } 4872918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim 488a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 48979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang void addAndStartAction(final FeatureAction action) { 49079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 49138db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo if (mService.isPowerStandbyOrTransient()) { 49238db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo Slog.w(TAG, "Skip the action during Standby: " + action); 49338db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return; 49438db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo } 49579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mActions.add(action); 49679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang action.start(); 49779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 49879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 49979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // See if we have an action of a given type in progress. 500a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 50179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang <T extends FeatureAction> boolean hasAction(final Class<T> clazz) { 50279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 50379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang for (FeatureAction action : mActions) { 50479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang if (action.getClass().equals(clazz)) { 50579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return true; 50679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 50779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 50879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return false; 50979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 51079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 51179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // Returns all actions matched with given class type. 512a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 51379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang <T extends FeatureAction> List<T> getActions(final Class<T> clazz) { 51479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 51543c23e273e1b78caf26899eca5a4f51df9d52400Jinsuk Kim List<T> actions = Collections.<T>emptyList(); 51679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang for (FeatureAction action : mActions) { 51779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang if (action.getClass().equals(clazz)) { 51843c23e273e1b78caf26899eca5a4f51df9d52400Jinsuk Kim if (actions.isEmpty()) { 51943c23e273e1b78caf26899eca5a4f51df9d52400Jinsuk Kim actions = new ArrayList<T>(); 52043c23e273e1b78caf26899eca5a4f51df9d52400Jinsuk Kim } 52179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang actions.add((T) action); 52279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 52379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 52479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return actions; 52579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 52679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 52779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang /** 52879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * Remove the given {@link FeatureAction} object from the action queue. 52979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * 53079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * @param action {@link FeatureAction} to remove 53179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang */ 532a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 53379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang void removeAction(final FeatureAction action) { 53479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 535c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo action.finish(false); 53679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mActions.remove(action); 53738db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo checkIfPendingActionsCleared(); 53879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 53979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 54079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // Remove all actions matched with the given Class type. 541a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 54279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang <T extends FeatureAction> void removeAction(final Class<T> clazz) { 543a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang assertRunOnServiceThread(); 54479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang removeActionExcept(clazz, null); 54579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 54679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 54779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // Remove all actions matched with the given Class type besides |exception|. 548a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 54979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang <T extends FeatureAction> void removeActionExcept(final Class<T> clazz, 55079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang final FeatureAction exception) { 55179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 55279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang Iterator<FeatureAction> iter = mActions.iterator(); 55379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang while (iter.hasNext()) { 55479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang FeatureAction action = iter.next(); 55579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang if (action != exception && action.getClass().equals(clazz)) { 556c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo action.finish(false); 557c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo iter.remove(); 55879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 55979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 56038db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo checkIfPendingActionsCleared(); 56179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 56279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 56338db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo protected void checkIfPendingActionsCleared() { 5644fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang if (mActions.isEmpty() && mPendingActionClearedCallback != null) { 56526ba7fddcaeb052710ca8672889830dabcbfd3acYuncheol Heo PendingActionClearedCallback callback = mPendingActionClearedCallback; 56626ba7fddcaeb052710ca8672889830dabcbfd3acYuncheol Heo // To prevent from calling the callback again during handling the callback itself. 56726ba7fddcaeb052710ca8672889830dabcbfd3acYuncheol Heo mPendingActionClearedCallback = null; 56826ba7fddcaeb052710ca8672889830dabcbfd3acYuncheol Heo callback.onCleared(this); 56938db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo } 57038db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo } 5714fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang 57279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected void assertRunOnServiceThread() { 57379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang if (Looper.myLooper() != mService.getServiceLooper()) { 57479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang throw new IllegalStateException("Should run on service thread."); 57579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 57679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 57779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 57879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang /** 57979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * Called when a hot-plug event issued. 58079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * 58179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * @param portId id of port where a hot-plug event happened 58279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * @param connected whether to connected or not on the event 58379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang */ 58479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang void onHotplug(int portId, boolean connected) { 58579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 58679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 58779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang final HdmiControlService getService() { 58879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mService; 58979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 59079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 591a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 59279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang final boolean isConnectedToArcPort(int path) { 593a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang assertRunOnServiceThread(); 59479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mService.isConnectedToArcPort(path); 59579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 59679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 59772b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim ActiveSource getActiveSource() { 59879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang synchronized (mLock) { 59979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mActiveSource; 60079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 60179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 60279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 60372b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim void setActiveSource(ActiveSource newActive) { 60472b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim setActiveSource(newActive.logicalAddress, newActive.physicalAddress); 60572b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim } 60672b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim 60772b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim void setActiveSource(HdmiCecDeviceInfo info) { 60872b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim setActiveSource(info.getLogicalAddress(), info.getPhysicalAddress()); 60972b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim } 61072b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim 61172b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim void setActiveSource(int logicalAddress, int physicalAddress) { 6128333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim synchronized (mLock) { 61372b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim mActiveSource.logicalAddress = logicalAddress; 61472b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim mActiveSource.physicalAddress = physicalAddress; 6158333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim } 6168333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim } 6178333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim 61879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang int getActivePath() { 61979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang synchronized (mLock) { 62079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mActiveRoutingPath; 62179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 62279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 62379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 6248333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim void setActivePath(int path) { 6258333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim synchronized (mLock) { 6268333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim mActiveRoutingPath = path; 6278333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim } 6288333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim } 6298333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim 63079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang /** 631a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim * Returns the ID of the active HDMI port. The active port is the one that has the active 632a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim * routing path connected to it directly or indirectly under the device hierarchy. 63379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang */ 634a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim int getActivePortId() { 63579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang synchronized (mLock) { 63679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mService.pathToPortId(mActiveRoutingPath); 63779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 63879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 63979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 640a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim /** 641a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim * Update the active port. 642a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim * 643a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim * @param portId the new active port id 644a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim */ 645a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim void setActivePortId(int portId) { 646a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim synchronized (mLock) { 647a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim // We update active routing path instead, since we get the active port id from 648a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim // the active routing path. 649a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim mActiveRoutingPath = mService.portIdToPath(portId); 650a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim } 651a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim } 652a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim 653a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 65479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang HdmiCecMessageCache getCecMessageCache() { 65579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 65679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mCecMessageCache; 65779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 65879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 659a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 66079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang int pathToPortId(int newPath) { 66179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 66279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mService.pathToPortId(newPath); 66379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 66438db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo 66538db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo /** 6664fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang * Called when the system goes to standby mode. 66738db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo * 66838db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo * @param initiatedByCec true if this power sequence is initiated 669b3e114af17c91a409e766e111e472f600f7b866cJungshik Jang * by the reception the CEC messages like <Standby> 67038db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo */ 6714fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang protected void onStandby(boolean initiatedByCec) {} 67238db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo 67338db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo /** 6744fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang * Disable device. {@code callback} is used to get notified when all pending 6754fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang * actions are completed or timeout is issued. 67638db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo * 6774fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang * @param initiatedByCec true if this sequence is initiated 678b3e114af17c91a409e766e111e472f600f7b866cJungshik Jang * by the reception the CEC messages like <Standby> 679b3e114af17c91a409e766e111e472f600f7b866cJungshik Jang * @param origialCallback callback interface to get notified when all pending actions are 680b3e114af17c91a409e766e111e472f600f7b866cJungshik Jang * cleared 68138db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo */ 682b3e114af17c91a409e766e111e472f600f7b866cJungshik Jang protected void disableDevice(boolean initiatedByCec, 683b3e114af17c91a409e766e111e472f600f7b866cJungshik Jang final PendingActionClearedCallback origialCallback) { 684b3e114af17c91a409e766e111e472f600f7b866cJungshik Jang mPendingActionClearedCallback = new PendingActionClearedCallback() { 685b3e114af17c91a409e766e111e472f600f7b866cJungshik Jang @Override 686b3e114af17c91a409e766e111e472f600f7b866cJungshik Jang public void onCleared(HdmiCecLocalDevice device) { 687b3e114af17c91a409e766e111e472f600f7b866cJungshik Jang mHandler.removeMessages(MSG_DISABLE_DEVICE_TIMEOUT); 688b3e114af17c91a409e766e111e472f600f7b866cJungshik Jang origialCallback.onCleared(device); 689b3e114af17c91a409e766e111e472f600f7b866cJungshik Jang } 690b3e114af17c91a409e766e111e472f600f7b866cJungshik Jang }; 6914fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang mHandler.sendMessageDelayed(Message.obtain(mHandler, MSG_DISABLE_DEVICE_TIMEOUT), 6924fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang DEVICE_CLEANUP_TIMEOUT); 6934fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang } 6944fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang 6954fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang @ServiceThreadOnly 6964fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang private void handleDisableDeviceTimeout() { 6974fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang assertRunOnServiceThread(); 6984fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang 6994fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang // If all actions are not cleared in DEVICE_CLEANUP_TIMEOUT, enforce to finish them. 7004fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang // onCleard will be called at the last action's finish method. 7014fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang Iterator<FeatureAction> iter = mActions.iterator(); 7024fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang while (iter.hasNext()) { 7034fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang FeatureAction action = iter.next(); 704c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo action.finish(false); 7054fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang iter.remove(); 7064fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang } 7074fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang } 708c068bb5a0468bf605b0398e6f0ea5721917de4eeJinsuk Kim 709c068bb5a0468bf605b0398e6f0ea5721917de4eeJinsuk Kim /** 710c068bb5a0468bf605b0398e6f0ea5721917de4eeJinsuk Kim * Send a key event to other device. 711c068bb5a0468bf605b0398e6f0ea5721917de4eeJinsuk Kim * 7124fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang * @param keyCode key code defined in {@link android.view.KeyEvent} 713c068bb5a0468bf605b0398e6f0ea5721917de4eeJinsuk Kim * @param isPressed {@code true} for key down event 714c068bb5a0468bf605b0398e6f0ea5721917de4eeJinsuk Kim */ 715c068bb5a0468bf605b0398e6f0ea5721917de4eeJinsuk Kim protected void sendKeyEvent(int keyCode, boolean isPressed) { 716c068bb5a0468bf605b0398e6f0ea5721917de4eeJinsuk Kim Slog.w(TAG, "sendKeyEvent not implemented"); 717c068bb5a0468bf605b0398e6f0ea5721917de4eeJinsuk Kim } 7182918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim} 719