HdmiCecLocalDevice.java revision 79c58a4b97f27ede6a1b680d2fece9c2a0edf7b7
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 192918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kimimport android.hardware.hdmi.HdmiCec; 201a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jangimport android.hardware.hdmi.HdmiCecDeviceInfo; 21092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jangimport android.hardware.hdmi.HdmiCecMessage; 2279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jangimport android.os.Looper; 23092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jangimport android.util.Slog; 242918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim 2579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jangimport com.android.internal.annotations.GuardedBy; 2679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 2779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jangimport java.util.ArrayList; 2879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jangimport java.util.Iterator; 2979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jangimport java.util.LinkedList; 3079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jangimport java.util.List; 3179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 322918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim/** 332918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim * Class that models a logical CEC device hosted in this system. Handles initialization, 342918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim * CEC commands that call for actions customized per device type. 352918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim */ 362918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kimabstract class HdmiCecLocalDevice { 37092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang private static final String TAG = "HdmiCecLocalDevice"; 382918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim 393ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang protected final HdmiControlService mService; 402918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim protected final int mDeviceType; 412918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim protected int mAddress; 422918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim protected int mPreferredAddress; 431a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang protected HdmiCecDeviceInfo mDeviceInfo; 442918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim 4579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // Logical address of the active source. 4679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang @GuardedBy("mLock") 4779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang private int mActiveSource; 4879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 4979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // Active routing path. Physical address of the active source but not all the time, such as 5079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // when the new active source does not claim itself to be one. Note that we don't keep 5179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // the active port id (or active input) since it can be gotten by {@link #pathToPortId(int)}. 5279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang @GuardedBy("mLock") 5379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang private int mActiveRoutingPath; 5479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 5579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // Set to true while the service is in normal mode. While set to false, no input change is 5679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // allowed. Used for situations where input change can confuse users such as channel auto-scan, 5779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // system upgrade, etc., a.k.a. "prohibit mode". 5879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang @GuardedBy("mLock") 5979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang private boolean mInputChangeEnabled; 6079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 6179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected final HdmiCecMessageCache mCecMessageCache = new HdmiCecMessageCache(); 6279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected final Object mLock; 6379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 6479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // A collection of FeatureAction. 6579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // Note that access to this collection should happen in service thread. 6679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang private final LinkedList<FeatureAction> mActions = new LinkedList<>(); 6779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 683ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang protected HdmiCecLocalDevice(HdmiControlService service, int deviceType) { 693ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang mService = service; 702918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim mDeviceType = deviceType; 712918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim mAddress = HdmiCec.ADDR_UNREGISTERED; 7279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mLock = service.getServiceLock(); 7379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 7479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // TODO: Get control flag from persistent storage 7579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mInputChangeEnabled = true; 762918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim } 772918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim 782918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim // Factory method that returns HdmiCecLocalDevice of corresponding type. 793ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang static HdmiCecLocalDevice create(HdmiControlService service, int deviceType) { 802918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim switch (deviceType) { 812918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim case HdmiCec.DEVICE_TV: 823ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang return new HdmiCecLocalDeviceTv(service); 832918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim case HdmiCec.DEVICE_PLAYBACK: 843ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang return new HdmiCecLocalDevicePlayback(service); 852918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim default: 862918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim return null; 872918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim } 882918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim } 892918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim 903ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang void init() { 913ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang mPreferredAddress = HdmiCec.ADDR_UNREGISTERED; 923ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang // TODO: load preferred address from permanent storage. 933ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang } 942918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim 958b308d93c8fdcc7304b33d9b445ae3807eae97c8Jungshik Jang /** 963ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang * Called once a logical address of the local device is allocated. 978b308d93c8fdcc7304b33d9b445ae3807eae97c8Jungshik Jang */ 988b308d93c8fdcc7304b33d9b445ae3807eae97c8Jungshik Jang protected abstract void onAddressAllocated(int logicalAddress); 998b308d93c8fdcc7304b33d9b445ae3807eae97c8Jungshik Jang 100092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang /** 101092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang * Dispatch incoming message. 102092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang * 103092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang * @param message incoming message 104092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang * @return true if consumed a message; otherwise, return false. 105092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang */ 106092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang final boolean dispatchMessage(HdmiCecMessage message) { 10779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 10879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 109092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang int dest = message.getDestination(); 110092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang if (dest != mAddress && dest != HdmiCec.ADDR_BROADCAST) { 111092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return false; 112092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 11379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // Cache incoming message. Note that it caches only white-listed one. 11479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mCecMessageCache.cacheMessage(message); 115092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return onMessage(message); 116092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 117092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang 11860cffce420db4c3395f86d3b9bb36003adf26f5dJungshik Jang protected final boolean onMessage(HdmiCecMessage message) { 11979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 12079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 12179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang if (dispatchMessageToAction(message)) { 12279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return true; 12379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 124092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang switch (message.getOpcode()) { 125092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang case HdmiCec.MESSAGE_GET_MENU_LANGUAGE: 126092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return handleGetMenuLanguage(message); 127092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang case HdmiCec.MESSAGE_GIVE_PHYSICAL_ADDRESS: 128092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return handleGivePhysicalAddress(); 129092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang case HdmiCec.MESSAGE_GIVE_OSD_NAME: 130092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return handleGiveOsdName(message); 131092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang case HdmiCec.MESSAGE_GIVE_DEVICE_VENDOR_ID: 132092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return handleGiveDeviceVendorId(); 133092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang case HdmiCec.MESSAGE_GET_CEC_VERSION: 134092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return handleGetCecVersion(message); 13560cffce420db4c3395f86d3b9bb36003adf26f5dJungshik Jang case HdmiCec.MESSAGE_REPORT_PHYSICAL_ADDRESS: 13660cffce420db4c3395f86d3b9bb36003adf26f5dJungshik Jang return handleReportPhysicalAddress(message); 13779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang case HdmiCec.MESSAGE_INITIATE_ARC: 13879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return handleInitiateArc(message); 13979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang case HdmiCec.MESSAGE_TERMINATE_ARC: 14079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return handleTerminateArc(message); 14179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang case HdmiCec.MESSAGE_SET_SYSTEM_AUDIO_MODE: 14279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return handleSetSystemAudioMode(message); 14379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang case HdmiCec.MESSAGE_SYSTEM_AUDIO_MODE_STATUS: 14479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return handleSystemAudioModeStatus(message); 145092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang default: 146092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return false; 147092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 148092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 149092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang 15079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang private boolean dispatchMessageToAction(HdmiCecMessage message) { 15179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang for (FeatureAction action : mActions) { 15279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang if (action.processCommand(message)) { 15379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return true; 15479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 15579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 15679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return false; 15779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 15879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 159092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang protected boolean handleGivePhysicalAddress() { 16079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 16179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 162092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang int physicalAddress = mService.getPhysicalAddress(); 163092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( 164092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang mAddress, physicalAddress, mDeviceType); 165092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang mService.sendCecCommand(cecMessage); 166092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return true; 167092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 168092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang 169092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang protected boolean handleGiveDeviceVendorId() { 17079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 17179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 172092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang int vendorId = mService.getVendorId(); 173092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildDeviceVendorIdCommand( 174092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang mAddress, vendorId); 175092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang mService.sendCecCommand(cecMessage); 176092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return true; 177092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 178092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang 179092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang protected boolean handleGetCecVersion(HdmiCecMessage message) { 18079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 18179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 182092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang int version = mService.getCecVersion(); 183092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildCecVersion(message.getDestination(), 184092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang message.getSource(), version); 185092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang mService.sendCecCommand(cecMessage); 186092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return true; 187092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 188092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang 189092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang protected boolean handleGetMenuLanguage(HdmiCecMessage message) { 19079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 19179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 192092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang Slog.w(TAG, "Only TV can handle <Get Menu Language>:" + message.toString()); 193092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang mService.sendCecCommand( 194092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang HdmiCecMessageBuilder.buildFeatureAbortCommand(mAddress, 195092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang message.getSource(), HdmiCec.MESSAGE_GET_MENU_LANGUAGE, 196092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang HdmiConstants.ABORT_UNRECOGNIZED_MODE)); 197092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return true; 198092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 199092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang 200092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang protected boolean handleGiveOsdName(HdmiCecMessage message) { 20179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 20279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 203092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang // Note that since this method is called after logical address allocation is done, 204092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang // mDeviceInfo should not be null. 205092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildSetOsdNameCommand( 206092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang mAddress, message.getSource(), mDeviceInfo.getDisplayName()); 207092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang if (cecMessage != null) { 208092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang mService.sendCecCommand(cecMessage); 209092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } else { 210092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang Slog.w(TAG, "Failed to build <Get Osd Name>:" + mDeviceInfo.getDisplayName()); 211092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 212092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return true; 213092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang } 214092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang 2150a3316bcfdac9f5f40d1349d97d10329c70f7e30Jinsuk Kim protected boolean handleVendorSpecificCommand(HdmiCecMessage message) { 2160a3316bcfdac9f5f40d1349d97d10329c70f7e30Jinsuk Kim return false; 2170a3316bcfdac9f5f40d1349d97d10329c70f7e30Jinsuk Kim } 2180a3316bcfdac9f5f40d1349d97d10329c70f7e30Jinsuk Kim 21960cffce420db4c3395f86d3b9bb36003adf26f5dJungshik Jang protected boolean handleReportPhysicalAddress(HdmiCecMessage message) { 22060cffce420db4c3395f86d3b9bb36003adf26f5dJungshik Jang return false; 22160cffce420db4c3395f86d3b9bb36003adf26f5dJungshik Jang } 22260cffce420db4c3395f86d3b9bb36003adf26f5dJungshik Jang 22379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected boolean handleSystemAudioModeStatus(HdmiCecMessage message) { 22479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return false; 22579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 22679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 22779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected boolean handleSetSystemAudioMode(HdmiCecMessage message) { 22879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return false; 22979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 23079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 23179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected boolean handleTerminateArc(HdmiCecMessage message) { 23279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return false; 23379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 23479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 23579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected boolean handleInitiateArc(HdmiCecMessage message) { 23679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return false; 23779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 23879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 2393ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang final void handleAddressAllocated(int logicalAddress) { 24079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 24179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 2423ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang mAddress = mPreferredAddress = logicalAddress; 2433ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang onAddressAllocated(logicalAddress); 2441a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang } 2451a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang 2461a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang HdmiCecDeviceInfo getDeviceInfo() { 24779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 2481a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang return mDeviceInfo; 2491a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang } 2501a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang 2511a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang void setDeviceInfo(HdmiCecDeviceInfo info) { 25279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 2531a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang mDeviceInfo = info; 2541a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang } 2551a4485dcd25ed036fb8de1a271b37121d8135f4eJungshik Jang 2562918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim // Returns true if the logical address is same as the argument. 2572918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim boolean isAddressOf(int addr) { 25879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 2592918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim return addr == mAddress; 2602918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim } 2612918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim 2622918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim // Resets the logical address to unregistered(15), meaning the logical device is invalid. 2632918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim void clearAddress() { 26479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 2652918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim mAddress = HdmiCec.ADDR_UNREGISTERED; 2662918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim } 2672918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim 2682918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim void setPreferredAddress(int addr) { 26979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 2702918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim mPreferredAddress = addr; 2712918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim } 2723ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang 2733ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang int getPreferredAddress() { 27479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 2753ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang return mPreferredAddress; 2763ee65720e91c7f92ad5a034d7052122a606aa8d5Jungshik Jang } 27779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 27879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang void addAndStartAction(final FeatureAction action) { 27979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 28079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mActions.add(action); 28179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang action.start(); 28279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 28379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 28479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // See if we have an action of a given type in progress. 28579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang <T extends FeatureAction> boolean hasAction(final Class<T> clazz) { 28679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 28779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang for (FeatureAction action : mActions) { 28879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang if (action.getClass().equals(clazz)) { 28979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return true; 29079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 29179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 29279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return false; 29379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 29479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 29579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // Returns all actions matched with given class type. 29679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang <T extends FeatureAction> List<T> getActions(final Class<T> clazz) { 29779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 29879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang ArrayList<T> actions = new ArrayList<>(); 29979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang for (FeatureAction action : mActions) { 30079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang if (action.getClass().equals(clazz)) { 30179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang actions.add((T) action); 30279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 30379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 30479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return actions; 30579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 30679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 30779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang /** 30879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * Remove the given {@link FeatureAction} object from the action queue. 30979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * 31079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * @param action {@link FeatureAction} to remove 31179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang */ 31279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang void removeAction(final FeatureAction action) { 31379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 31479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mActions.remove(action); 31579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 31679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 31779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // Remove all actions matched with the given Class type. 31879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang <T extends FeatureAction> void removeAction(final Class<T> clazz) { 31979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang removeActionExcept(clazz, null); 32079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 32179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 32279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // Remove all actions matched with the given Class type besides |exception|. 32379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang <T extends FeatureAction> void removeActionExcept(final Class<T> clazz, 32479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang final FeatureAction exception) { 32579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 32679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang Iterator<FeatureAction> iter = mActions.iterator(); 32779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang while (iter.hasNext()) { 32879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang FeatureAction action = iter.next(); 32979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang if (action != exception && action.getClass().equals(clazz)) { 33079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang action.clear(); 33179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mActions.remove(action); 33279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 33379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 33479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 33579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 33679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected void assertRunOnServiceThread() { 33779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang if (Looper.myLooper() != mService.getServiceLooper()) { 33879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang throw new IllegalStateException("Should run on service thread."); 33979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 34079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 34179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 34279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang /** 34379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * Called when a hot-plug event issued. 34479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * 34579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * @param portId id of port where a hot-plug event happened 34679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * @param connected whether to connected or not on the event 34779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang */ 34879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang void onHotplug(int portId, boolean connected) { 34979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 35079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 35179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang final HdmiControlService getService() { 35279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mService; 35379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 35479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 35579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang final boolean isConnectedToArcPort(int path) { 35679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mService.isConnectedToArcPort(path); 35779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 35879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 35979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang int getActiveSource() { 36079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang synchronized (mLock) { 36179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mActiveSource; 36279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 36379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 36479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 36579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang /** 36679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * Returns the active routing path. 36779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang */ 36879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang int getActivePath() { 36979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang synchronized (mLock) { 37079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mActiveRoutingPath; 37179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 37279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 37379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 37479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang /** 37579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * Returns the ID of the active HDMI port. The active input is the port that has the active 37679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * routing path connected directly or indirectly under the device hierarchy. 37779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang */ 37879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang int getActiveInput() { 37979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang synchronized (mLock) { 38079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mService.pathToPortId(mActiveRoutingPath); 38179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 38279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 38379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 38479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang void updateActiveDevice(int logicalAddress, int physicalAddress) { 38579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang synchronized (mLock) { 38679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mActiveSource = logicalAddress; 38779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mActiveRoutingPath = physicalAddress; 38879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 38979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 39079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 39179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang void setInputChangeEnabled(boolean enabled) { 39279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang synchronized (mLock) { 39379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mInputChangeEnabled = enabled; 39479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 39579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 39679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 39779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang boolean isInPresetInstallationMode() { 39879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang synchronized (mLock) { 39979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return !mInputChangeEnabled; 40079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 40179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 40279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 40379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang /** 40479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * Whether the given path is located in the tail of current active path. 40579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * 40679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * @param path to be tested 40779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * @return true if the given path is located in the tail of current active path; otherwise, 40879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * false 40979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang */ 41079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // TODO: move this to local device tv. 41179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang boolean isTailOfActivePath(int path) { 41279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang synchronized (mLock) { 41379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang // If active routing path is internal source, return false. 41479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang if (mActiveRoutingPath == 0) { 41579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return false; 41679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 41779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang for (int i = 12; i >= 0; i -= 4) { 41879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang int curActivePath = (mActiveRoutingPath >> i) & 0xF; 41979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang if (curActivePath == 0) { 42079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return true; 42179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } else { 42279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang int curPath = (path >> i) & 0xF; 42379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang if (curPath != curActivePath) { 42479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return false; 42579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 42679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 42779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 42879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return false; 42979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 43079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 43179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 43279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang HdmiCecMessageCache getCecMessageCache() { 43379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 43479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mCecMessageCache; 43579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 43679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 43779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang int pathToPortId(int newPath) { 43879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang assertRunOnServiceThread(); 43979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mService.pathToPortId(newPath); 44079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 4412918e9e133de8066ab497a5f8dac1c310c792767Jinsuk Kim} 442