HdmiCecLocalDevice.java revision b6591b8e5399099dc6b7693e0fc719b613aba89c
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; 23af2acf0447aff34450cde2bcfb35dff9cf631729Jinsuk Kimimport android.os.SystemProperties; 24092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jangimport android.util.Slog; 252918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim 2679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jangimport com.android.internal.annotations.GuardedBy; 27a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jangimport com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly; 2879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 2979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jangimport java.util.ArrayList; 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 5279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // Logical address of the active source. 5379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang @GuardedBy("mLock") 5479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang private int mActiveSource; 5579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 5679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // Active routing path. Physical address of the active source but not all the time, such as 5779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // when the new active source does not claim itself to be one. Note that we don't keep 5879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // the active port id (or active input) since it can be gotten by {@link #pathToPortId(int)}. 5979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang @GuardedBy("mLock") 6079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang private int mActiveRoutingPath; 6179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 6279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected final HdmiCecMessageCache mCecMessageCache = new HdmiCecMessageCache(); 6379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected final Object mLock; 6479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 6579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // A collection of FeatureAction. 6679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // Note that access to this collection should happen in service thread. 6779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang private final LinkedList<FeatureAction> mActions = new LinkedList<>(); 6879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 69c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo private final Handler mHandler = new Handler () { 704fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang @Override 714fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang public void handleMessage(Message msg) { 724fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang switch (msg.what) { 734fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang case MSG_DISABLE_DEVICE_TIMEOUT: 744fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang handleDisableDeviceTimeout(); 754fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang break; 764fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang } 774fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang } 784fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang }; 794fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang 804fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang /** 814fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang * A callback interface to get notified when all pending action is cleared. 824fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang * It can be called when timeout happened. 834fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang */ 844fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang interface PendingActionClearedCallback { 854fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang void onCleared(HdmiCecLocalDevice device); 864fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang } 874fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang 884fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang protected PendingActionClearedCallback mPendingActionClearedCallback; 894fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang 903ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang protected HdmiCecLocalDevice(HdmiControlService service, int deviceType) { 913ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang mService = service; 922918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim mDeviceType = deviceType; 93c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim mAddress = Constants.ADDR_UNREGISTERED; 9479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mLock = service.getServiceLock(); 952918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim } 962918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim 972918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim // Factory method that returns HdmiCecLocalDevice of corresponding type. 983ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang static HdmiCecLocalDevice create(HdmiControlService service, int deviceType) { 992918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim switch (deviceType) { 100c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case HdmiCecDeviceInfo.DEVICE_TV: 1013ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang return new HdmiCecLocalDeviceTv(service); 102c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case HdmiCecDeviceInfo.DEVICE_PLAYBACK: 1033ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang return new HdmiCecLocalDevicePlayback(service); 1042918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim default: 1052918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim return null; 1062918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim } 1072918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim } 1082918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim 109a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 1103ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang void init() { 111a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang assertRunOnServiceThread(); 112af2acf0447aff34450cde2bcfb35dff9cf631729Jinsuk Kim mPreferredAddress = getPreferredAddress(); 1133ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang } 1142918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim 1158b308d93c8fdcc7304b33d9b445ae3807eae97c8Jungshik Jang /** 1163ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang * Called once a logical address of the local device is allocated. 1178b308d93c8fdcc7304b33d9b445ae3807eae97c8Jungshik Jang */ 118a9f10629f4bc1a82761917645ff4d2b6d42e47b3Jungshik Jang protected abstract void onAddressAllocated(int logicalAddress, boolean fromBootup); 1198b308d93c8fdcc7304b33d9b445ae3807eae97c8Jungshik Jang 120092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang /** 121af2acf0447aff34450cde2bcfb35dff9cf631729Jinsuk Kim * Get the preferred logical address from system properties. 122af2acf0447aff34450cde2bcfb35dff9cf631729Jinsuk Kim */ 123af2acf0447aff34450cde2bcfb35dff9cf631729Jinsuk Kim protected abstract int getPreferredAddress(); 124af2acf0447aff34450cde2bcfb35dff9cf631729Jinsuk Kim 125af2acf0447aff34450cde2bcfb35dff9cf631729Jinsuk Kim /** 126af2acf0447aff34450cde2bcfb35dff9cf631729Jinsuk Kim * Set the preferred logical address to system properties. 127af2acf0447aff34450cde2bcfb35dff9cf631729Jinsuk Kim */ 128af2acf0447aff34450cde2bcfb35dff9cf631729Jinsuk Kim protected abstract void setPreferredAddress(int addr); 129af2acf0447aff34450cde2bcfb35dff9cf631729Jinsuk Kim 130af2acf0447aff34450cde2bcfb35dff9cf631729Jinsuk Kim /** 131092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang * Dispatch incoming message. 132092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang * 133092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang * @param message incoming message 134092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang * @return true if consumed a message; otherwise, return false. 135092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang */ 136a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 137092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang final boolean dispatchMessage(HdmiCecMessage message) { 13879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 139092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang int dest = message.getDestination(); 140c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim if (dest != mAddress && dest != Constants.ADDR_BROADCAST) { 141092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return false; 142092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 14379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // Cache incoming message. Note that it caches only white-listed one. 14479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mCecMessageCache.cacheMessage(message); 145092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return onMessage(message); 146092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 147092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang 148a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 14960cffce420db4c3395f86d3b9bb36003adf26f5dJungshik Jang protected final boolean onMessage(HdmiCecMessage message) { 15079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 15179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang if (dispatchMessageToAction(message)) { 15279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return true; 15379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 154092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang switch (message.getOpcode()) { 155c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_ACTIVE_SOURCE: 1568333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim return handleActiveSource(message); 157c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_INACTIVE_SOURCE: 1588333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim return handleInactiveSource(message); 159c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_REQUEST_ACTIVE_SOURCE: 1608333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim return handleRequestActiveSource(message); 161c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_GET_MENU_LANGUAGE: 162092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return handleGetMenuLanguage(message); 163c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_GIVE_PHYSICAL_ADDRESS: 164092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return handleGivePhysicalAddress(); 165c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_GIVE_OSD_NAME: 166092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return handleGiveOsdName(message); 167c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_GIVE_DEVICE_VENDOR_ID: 168092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return handleGiveDeviceVendorId(); 169c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_GET_CEC_VERSION: 170092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return handleGetCecVersion(message); 171c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS: 17260cffce420db4c3395f86d3b9bb36003adf26f5dJungshik Jang return handleReportPhysicalAddress(message); 173c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_ROUTING_CHANGE: 17492b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim return handleRoutingChange(message); 175c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_INITIATE_ARC: 17679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return handleInitiateArc(message); 177c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_TERMINATE_ARC: 17879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return handleTerminateArc(message); 179c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE: 18079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return handleSetSystemAudioMode(message); 181c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_SYSTEM_AUDIO_MODE_STATUS: 18279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return handleSystemAudioModeStatus(message); 183c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_REPORT_AUDIO_STATUS: 1848fa36b110be29d92a9aba070fa4666eefb14b584Jungshik Jang return handleReportAudioStatus(message); 185c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_STANDBY: 18638db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return handleStandby(message); 187c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_TEXT_VIEW_ON: 18838db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return handleTextViewOn(message); 189c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_IMAGE_VIEW_ON: 19038db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return handleImageViewOn(message); 191c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_USER_CONTROL_PRESSED: 19238db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return handleUserControlPressed(message); 193c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_SET_STREAM_PATH: 19438db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return handleSetStreamPath(message); 195c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim case Constants.MESSAGE_GIVE_DEVICE_POWER_STATUS: 19638db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return handleGiveDevicePowerStatus(message); 197119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim case Constants.MESSAGE_VENDOR_COMMAND: 198119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim return handleVendorCommand(message); 199119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim case Constants.MESSAGE_VENDOR_COMMAND_WITH_ID: 200119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim return handleVendorCommandWithId(message); 2018f2ed357a23fac4a55da43d20138b438b4ac79a7Jungshik Jang case Constants.MESSAGE_SET_OSD_NAME: 2028f2ed357a23fac4a55da43d20138b438b4ac79a7Jungshik Jang return handleSetOsdName(message); 203b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang case Constants.MESSAGE_RECORD_TV_SCREEN: 204b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang return handleRecordTvScreen(message); 205092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang default: 206092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return false; 207092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 208092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 209092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang 210a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 21179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang private boolean dispatchMessageToAction(HdmiCecMessage message) { 212a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang assertRunOnServiceThread(); 21379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang for (FeatureAction action : mActions) { 21479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang if (action.processCommand(message)) { 21579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return true; 21679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 21779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 21879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return false; 21979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 22079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 221a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 222092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang protected boolean handleGivePhysicalAddress() { 22379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 22479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 225092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang int physicalAddress = mService.getPhysicalAddress(); 226092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( 227092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang mAddress, physicalAddress, mDeviceType); 228092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang mService.sendCecCommand(cecMessage); 229092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return true; 230092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 231092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang 232a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 233092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang protected boolean handleGiveDeviceVendorId() { 23479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 235092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang int vendorId = mService.getVendorId(); 236092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildDeviceVendorIdCommand( 237092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang mAddress, vendorId); 238092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang mService.sendCecCommand(cecMessage); 239092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return true; 240092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 241092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang 242a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 243092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang protected boolean handleGetCecVersion(HdmiCecMessage message) { 24479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 245092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang int version = mService.getCecVersion(); 246092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildCecVersion(message.getDestination(), 247092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang message.getSource(), version); 248092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang mService.sendCecCommand(cecMessage); 249092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return true; 250092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 251092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang 252a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 2538333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim protected boolean handleActiveSource(HdmiCecMessage message) { 2548333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim return false; 2558333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim } 2568333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim 2578333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim @ServiceThreadOnly 2588333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim protected boolean handleInactiveSource(HdmiCecMessage message) { 2598333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim return false; 2608333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim } 2618333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim 2628333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim @ServiceThreadOnly 2638333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim protected boolean handleRequestActiveSource(HdmiCecMessage message) { 2648333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim return false; 2658333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim } 2668333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim 2678333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim @ServiceThreadOnly 268092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang protected boolean handleGetMenuLanguage(HdmiCecMessage message) { 26979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 270092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang Slog.w(TAG, "Only TV can handle <Get Menu Language>:" + message.toString()); 271092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang mService.sendCecCommand( 272092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang HdmiCecMessageBuilder.buildFeatureAbortCommand(mAddress, 273c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim message.getSource(), Constants.MESSAGE_GET_MENU_LANGUAGE, 274c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim Constants.ABORT_UNRECOGNIZED_MODE)); 275092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return true; 276092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 277092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang 278a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 279092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang protected boolean handleGiveOsdName(HdmiCecMessage message) { 28079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 281092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang // Note that since this method is called after logical address allocation is done, 282092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang // mDeviceInfo should not be null. 283092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildSetOsdNameCommand( 284092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang mAddress, message.getSource(), mDeviceInfo.getDisplayName()); 285092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang if (cecMessage != null) { 286092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang mService.sendCecCommand(cecMessage); 287092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } else { 288092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang Slog.w(TAG, "Failed to build <Get Osd Name>:" + mDeviceInfo.getDisplayName()); 289092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 290092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return true; 291092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 292092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang 29392b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim protected boolean handleRoutingChange(HdmiCecMessage message) { 29492b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim return false; 29592b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim } 29692b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim 29760cffce420db4c3395f86d3b9bb36003adf26f5dJungshik Jang protected boolean handleReportPhysicalAddress(HdmiCecMessage message) { 29860cffce420db4c3395f86d3b9bb36003adf26f5dJungshik Jang return false; 29960cffce420db4c3395f86d3b9bb36003adf26f5dJungshik Jang } 30060cffce420db4c3395f86d3b9bb36003adf26f5dJungshik Jang 30179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected boolean handleSystemAudioModeStatus(HdmiCecMessage message) { 30279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return false; 30379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 30479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 30579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected boolean handleSetSystemAudioMode(HdmiCecMessage message) { 30679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return false; 30779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 30879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 30979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected boolean handleTerminateArc(HdmiCecMessage message) { 31079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return false; 31179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 31279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 31379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected boolean handleInitiateArc(HdmiCecMessage message) { 31479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return false; 3158fa36b110be29d92a9aba070fa4666eefb14b584Jungshik Jang } 3168fa36b110be29d92a9aba070fa4666eefb14b584Jungshik Jang 3178fa36b110be29d92a9aba070fa4666eefb14b584Jungshik Jang protected boolean handleReportAudioStatus(HdmiCecMessage message) { 3188fa36b110be29d92a9aba070fa4666eefb14b584Jungshik Jang return false; 31979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 32079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 321a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 32238db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo protected boolean handleStandby(HdmiCecMessage message) { 32338db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo assertRunOnServiceThread(); 32438db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo // Seq #12 3254d43d93743222311c6377d4904c19ccb93699d3bJinsuk Kim if (mService.isControlEnabled() && !mService.isProhibitMode() 32638db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo && mService.isPowerOnOrTransient()) { 32738db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo mService.standby(); 32838db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return true; 32938db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo } 33038db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return false; 33138db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo } 33238db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo 33338db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo @ServiceThreadOnly 33438db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo protected boolean handleUserControlPressed(HdmiCecMessage message) { 33538db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo assertRunOnServiceThread(); 33638db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo if (mService.isPowerOnOrTransient() && isPowerOffOrToggleCommand(message)) { 33738db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo mService.standby(); 33838db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return true; 33938db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo } else if (mService.isPowerStandbyOrTransient() && isPowerOnOrToggleCommand(message)) { 34038db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo mService.wakeUp(); 34138db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return true; 34238db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo } 34338db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return false; 34438db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo } 34538db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo 34638db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo private static boolean isPowerOnOrToggleCommand(HdmiCecMessage message) { 34738db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo byte[] params = message.getParams(); 348c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim return message.getOpcode() == Constants.MESSAGE_USER_CONTROL_PRESSED 349210d73df0b77b4c8be67ecc92afb238dc8c7ccfaJungshik Jang && (params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER 350210d73df0b77b4c8be67ecc92afb238dc8c7ccfaJungshik Jang || params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER_ON_FUNCTION 351210d73df0b77b4c8be67ecc92afb238dc8c7ccfaJungshik Jang || params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER_TOGGLE_FUNCTION); 35238db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo } 35338db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo 35438db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo private static boolean isPowerOffOrToggleCommand(HdmiCecMessage message) { 35538db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo byte[] params = message.getParams(); 356c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim return message.getOpcode() == Constants.MESSAGE_USER_CONTROL_PRESSED 357210d73df0b77b4c8be67ecc92afb238dc8c7ccfaJungshik Jang && (params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER 358210d73df0b77b4c8be67ecc92afb238dc8c7ccfaJungshik Jang || params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER_OFF_FUNCTION 359210d73df0b77b4c8be67ecc92afb238dc8c7ccfaJungshik Jang || params[0] == HdmiCecKeycode.CEC_KEYCODE_POWER_TOGGLE_FUNCTION); 36038db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo } 36138db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo 36238db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo protected boolean handleTextViewOn(HdmiCecMessage message) { 36338db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return false; 36438db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo } 36538db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo 36638db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo protected boolean handleImageViewOn(HdmiCecMessage message) { 36738db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return false; 36838db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo } 36938db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo 37038db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo protected boolean handleSetStreamPath(HdmiCecMessage message) { 37138db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return false; 37238db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo } 37338db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo 37438db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo protected boolean handleGiveDevicePowerStatus(HdmiCecMessage message) { 37538db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo mService.sendCecCommand(HdmiCecMessageBuilder.buildReportPowerStatus( 37638db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo mAddress, message.getSource(), mService.getPowerStatus())); 37738db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return true; 37838db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo } 37938db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo 380119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim protected boolean handleVendorCommand(HdmiCecMessage message) { 381119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim mService.invokeVendorCommandListeners(mDeviceType, message.getSource(), 382119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim message.getParams(), false); 383119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim return true; 384119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim } 385119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim 386119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim protected boolean handleVendorCommandWithId(HdmiCecMessage message) { 387119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim byte[] params = message.getParams(); 388119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim int vendorId = HdmiUtils.threeBytesToInt(params); 389119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim if (vendorId == mService.getVendorId()) { 390119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim mService.invokeVendorCommandListeners(mDeviceType, message.getSource(), params, true); 391119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim } else if (message.getDestination() != Constants.ADDR_BROADCAST && 392119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim message.getSource() != Constants.ADDR_UNREGISTERED) { 393119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim Slog.v(TAG, "Wrong direct vendor command. Replying with <Feature Abort>"); 394119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim mService.sendCecCommand(HdmiCecMessageBuilder.buildFeatureAbortCommand(mAddress, 395119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim message.getSource(), Constants.MESSAGE_VENDOR_COMMAND_WITH_ID, 396119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim Constants.ABORT_UNRECOGNIZED_MODE)); 397119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim } else { 398119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim Slog.v(TAG, "Wrong broadcast vendor command. Ignoring"); 399119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim } 400119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim return true; 401119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim } 402119160a68195bcb2f5bdf4a269807e01228eca97Jinsuk Kim 4038f2ed357a23fac4a55da43d20138b438b4ac79a7Jungshik Jang protected boolean handleSetOsdName(HdmiCecMessage message) { 4048f2ed357a23fac4a55da43d20138b438b4ac79a7Jungshik Jang // The default behavior of <Set Osd Name> is doing nothing. 4058f2ed357a23fac4a55da43d20138b438b4ac79a7Jungshik Jang return true; 4068f2ed357a23fac4a55da43d20138b438b4ac79a7Jungshik Jang } 4078f2ed357a23fac4a55da43d20138b438b4ac79a7Jungshik Jang 408b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang protected boolean handleRecordTvScreen(HdmiCecMessage message) { 409b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang // The default behavior of <Record TV Screen> is replying <Feature Abort> with "Refused". 410b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang mService.sendCecCommand(HdmiCecMessageBuilder.buildFeatureAbortCommand(mAddress, 411b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang message.getSource(), message.getOpcode(), Constants.ABORT_REFUSED)); 412b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang return true; 413b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang } 414b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang 41538db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo @ServiceThreadOnly 416a9f10629f4bc1a82761917645ff4d2b6d42e47b3Jungshik Jang final void handleAddressAllocated(int logicalAddress, boolean fromBootup) { 41779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 4183ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang mAddress = mPreferredAddress = logicalAddress; 419a9f10629f4bc1a82761917645ff4d2b6d42e47b3Jungshik Jang onAddressAllocated(logicalAddress, fromBootup); 420af2acf0447aff34450cde2bcfb35dff9cf631729Jinsuk Kim setPreferredAddress(logicalAddress); 4211a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang } 4221a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang 423a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 4241a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang HdmiCecDeviceInfo getDeviceInfo() { 42579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 4261a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang return mDeviceInfo; 4271a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang } 4281a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang 429a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 4301a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang void setDeviceInfo(HdmiCecDeviceInfo info) { 43179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 4321a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang mDeviceInfo = info; 4331a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang } 4341a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang 4352918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim // Returns true if the logical address is same as the argument. 436a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 4372918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim boolean isAddressOf(int addr) { 43879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 4392918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim return addr == mAddress; 4402918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim } 4412918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim 4422918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim // Resets the logical address to unregistered(15), meaning the logical device is invalid. 443a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 4442918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim void clearAddress() { 44579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 446c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim mAddress = Constants.ADDR_UNREGISTERED; 4472918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim } 4482918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim 449a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 45079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang void addAndStartAction(final FeatureAction action) { 45179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 45238db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo if (mService.isPowerStandbyOrTransient()) { 45338db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo Slog.w(TAG, "Skip the action during Standby: " + action); 45438db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo return; 45538db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo } 45679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mActions.add(action); 45779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang action.start(); 45879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 45979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 46079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // See if we have an action of a given type in progress. 461a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 46279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang <T extends FeatureAction> boolean hasAction(final Class<T> clazz) { 46379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 46479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang for (FeatureAction action : mActions) { 46579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang if (action.getClass().equals(clazz)) { 46679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return true; 46779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 46879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 46979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return false; 47079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 47179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 47279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // Returns all actions matched with given class type. 473a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 47479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang <T extends FeatureAction> List<T> getActions(final Class<T> clazz) { 47579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 47679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang ArrayList<T> actions = new ArrayList<>(); 47779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang for (FeatureAction action : mActions) { 47879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang if (action.getClass().equals(clazz)) { 47979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang actions.add((T) action); 48079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 48179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 48279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return actions; 48379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 48479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 48579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang /** 48679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * Remove the given {@link FeatureAction} object from the action queue. 48779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * 48879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * @param action {@link FeatureAction} to remove 48979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang */ 490a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 49179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang void removeAction(final FeatureAction action) { 49279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 493c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo action.finish(false); 49479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mActions.remove(action); 49538db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo checkIfPendingActionsCleared(); 49679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 49779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 49879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // Remove all actions matched with the given Class type. 499a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 50079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang <T extends FeatureAction> void removeAction(final Class<T> clazz) { 501a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang assertRunOnServiceThread(); 50279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang removeActionExcept(clazz, null); 50379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 50479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 50579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // Remove all actions matched with the given Class type besides |exception|. 506a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 50779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang <T extends FeatureAction> void removeActionExcept(final Class<T> clazz, 50879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang final FeatureAction exception) { 50979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 51079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang Iterator<FeatureAction> iter = mActions.iterator(); 51179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang while (iter.hasNext()) { 51279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang FeatureAction action = iter.next(); 51379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang if (action != exception && action.getClass().equals(clazz)) { 514c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo action.finish(false); 515c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo iter.remove(); 51679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 51779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 51838db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo checkIfPendingActionsCleared(); 51979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 52079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 52138db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo protected void checkIfPendingActionsCleared() { 5224fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang if (mActions.isEmpty() && mPendingActionClearedCallback != null) { 5234fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang mPendingActionClearedCallback.onCleared(this); 52438db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo } 52538db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo } 5264fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang 52779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected void assertRunOnServiceThread() { 52879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang if (Looper.myLooper() != mService.getServiceLooper()) { 52979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang throw new IllegalStateException("Should run on service thread."); 53079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 53179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 53279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 53379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang /** 53479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * Called when a hot-plug event issued. 53579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * 53679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * @param portId id of port where a hot-plug event happened 53779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * @param connected whether to connected or not on the event 53879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang */ 53979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang void onHotplug(int portId, boolean connected) { 54079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 54179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 54279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang final HdmiControlService getService() { 54379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mService; 54479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 54579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 546a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 54779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang final boolean isConnectedToArcPort(int path) { 548a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang assertRunOnServiceThread(); 54979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mService.isConnectedToArcPort(path); 55079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 55179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 55279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang int getActiveSource() { 55379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang synchronized (mLock) { 55479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mActiveSource; 55579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 55679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 55779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 5588333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim void setActiveSource(int source) { 5598333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim synchronized (mLock) { 5608333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim mActiveSource = source; 5618333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim } 5628333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim } 5638333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim 56479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang int getActivePath() { 56579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang synchronized (mLock) { 56679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mActiveRoutingPath; 56779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 56879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 56979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 5708333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim void setActivePath(int path) { 5718333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim synchronized (mLock) { 5728333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim mActiveRoutingPath = path; 5738333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim } 5748333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim } 5758333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim 57679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang /** 577a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim * Returns the ID of the active HDMI port. The active port is the one that has the active 578a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim * routing path connected to it directly or indirectly under the device hierarchy. 57979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang */ 580a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim int getActivePortId() { 58179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang synchronized (mLock) { 58279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mService.pathToPortId(mActiveRoutingPath); 58379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 58479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 58579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 586a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim /** 587a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim * Update the active port. 588a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim * 589a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim * @param portId the new active port id 590a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim */ 591a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim void setActivePortId(int portId) { 592a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim synchronized (mLock) { 593a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim // We update active routing path instead, since we get the active port id from 594a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim // the active routing path. 595a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim mActiveRoutingPath = mService.portIdToPath(portId); 596a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim } 597a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim } 598a062a9339add79a84862a34e363e3e454a6ec435Jinsuk Kim 59979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang void updateActiveDevice(int logicalAddress, int physicalAddress) { 60079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang synchronized (mLock) { 60179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mActiveSource = logicalAddress; 60279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mActiveRoutingPath = physicalAddress; 60379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 60479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 60579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 606a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 60779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang HdmiCecMessageCache getCecMessageCache() { 60879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 60979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mCecMessageCache; 61079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 61179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 612a5b7414970c85217e88015e78ecbc5ba093dead3Jungshik Jang @ServiceThreadOnly 61379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang int pathToPortId(int newPath) { 61479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 61579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mService.pathToPortId(newPath); 61679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 61738db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo 61838db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo /** 6194fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang * Called when the system goes to standby mode. 62038db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo * 62138db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo * @param initiatedByCec true if this power sequence is initiated 622b3e114af17c91a409e766e111e472f600f7b866cJungshik Jang * by the reception the CEC messages like <Standby> 62338db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo */ 6244fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang protected void onStandby(boolean initiatedByCec) {} 62538db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo 62638db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo /** 6274fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang * Disable device. {@code callback} is used to get notified when all pending 6284fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang * actions are completed or timeout is issued. 62938db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo * 6304fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang * @param initiatedByCec true if this sequence is initiated 631b3e114af17c91a409e766e111e472f600f7b866cJungshik Jang * by the reception the CEC messages like <Standby> 632b3e114af17c91a409e766e111e472f600f7b866cJungshik Jang * @param origialCallback callback interface to get notified when all pending actions are 633b3e114af17c91a409e766e111e472f600f7b866cJungshik Jang * cleared 63438db629d897e9d7c8e31ce0a7e985981e3e12996Yuncheol Heo */ 635b3e114af17c91a409e766e111e472f600f7b866cJungshik Jang protected void disableDevice(boolean initiatedByCec, 636b3e114af17c91a409e766e111e472f600f7b866cJungshik Jang final PendingActionClearedCallback origialCallback) { 637b3e114af17c91a409e766e111e472f600f7b866cJungshik Jang mPendingActionClearedCallback = new PendingActionClearedCallback() { 638b3e114af17c91a409e766e111e472f600f7b866cJungshik Jang @Override 639b3e114af17c91a409e766e111e472f600f7b866cJungshik Jang public void onCleared(HdmiCecLocalDevice device) { 640b3e114af17c91a409e766e111e472f600f7b866cJungshik Jang mHandler.removeMessages(MSG_DISABLE_DEVICE_TIMEOUT); 641b3e114af17c91a409e766e111e472f600f7b866cJungshik Jang origialCallback.onCleared(device); 642b3e114af17c91a409e766e111e472f600f7b866cJungshik Jang } 643b3e114af17c91a409e766e111e472f600f7b866cJungshik Jang }; 6444fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang mHandler.sendMessageDelayed(Message.obtain(mHandler, MSG_DISABLE_DEVICE_TIMEOUT), 6454fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang DEVICE_CLEANUP_TIMEOUT); 6464fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang } 6474fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang 6484fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang @ServiceThreadOnly 6494fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang private void handleDisableDeviceTimeout() { 6504fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang assertRunOnServiceThread(); 6514fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang 6524fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang // If all actions are not cleared in DEVICE_CLEANUP_TIMEOUT, enforce to finish them. 6534fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang // onCleard will be called at the last action's finish method. 6544fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang Iterator<FeatureAction> iter = mActions.iterator(); 6554fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang while (iter.hasNext()) { 6564fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang FeatureAction action = iter.next(); 657c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo action.finish(false); 6584fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang iter.remove(); 6594fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang } 6604fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang } 661c068bb5a0468bf605b0398e6f0ea5721917de4eeJinsuk Kim 662c068bb5a0468bf605b0398e6f0ea5721917de4eeJinsuk Kim /** 663c068bb5a0468bf605b0398e6f0ea5721917de4eeJinsuk Kim * Send a key event to other device. 664c068bb5a0468bf605b0398e6f0ea5721917de4eeJinsuk Kim * 6654fc1d105fc279bf7df6c876e160672866bdad8e7Jungshik Jang * @param keyCode key code defined in {@link android.view.KeyEvent} 666c068bb5a0468bf605b0398e6f0ea5721917de4eeJinsuk Kim * @param isPressed {@code true} for key down event 667c068bb5a0468bf605b0398e6f0ea5721917de4eeJinsuk Kim */ 668c068bb5a0468bf605b0398e6f0ea5721917de4eeJinsuk Kim protected void sendKeyEvent(int keyCode, boolean isPressed) { 669c068bb5a0468bf605b0398e6f0ea5721917de4eeJinsuk Kim Slog.w(TAG, "sendKeyEvent not implemented"); 670c068bb5a0468bf605b0398e6f0ea5721917de4eeJinsuk Kim } 6712918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim} 672