TvInputHardwareManager.java revision ca17a9029dd7b1b87c155e68476eae5ee4efbede
1c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim/* 2c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * Copyright (C) 2014 The Android Open Source Project 3c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * 4c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * Licensed under the Apache License, Version 2.0 (the "License"); 5c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * you may not use this file except in compliance with the License. 6c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * You may obtain a copy of the License at 7c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * 8c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * http://www.apache.org/licenses/LICENSE-2.0 9c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * 10c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * Unless required by applicable law or agreed to in writing, software 11c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * distributed under the License is distributed on an "AS IS" BASIS, 12c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * See the License for the specific language governing permissions and 14c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * limitations under the License. 15c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim */ 16c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 17c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kimpackage com.android.server.tv; 18c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 19969167dc05a6485a32d160895871cff46fd81884Wonsik Kimimport static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED; 20969167dc05a6485a32d160895871cff46fd81884Wonsik Kimimport static android.media.tv.TvInputManager.INPUT_STATE_DISCONNECTED; 21969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 22c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kimimport android.content.Context; 23b2b3151a42bd563669b222b82efb64e294dc9049Jinsuk Kimimport android.content.Intent; 24187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kimimport android.hardware.hdmi.HdmiCecDeviceInfo; 25969167dc05a6485a32d160895871cff46fd81884Wonsik Kimimport android.hardware.hdmi.HdmiHotplugEvent; 267474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kimimport android.hardware.hdmi.IHdmiControlService; 27187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kimimport android.hardware.hdmi.IHdmiDeviceEventListener; 287474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kimimport android.hardware.hdmi.IHdmiHotplugEventListener; 297474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kimimport android.hardware.hdmi.IHdmiInputChangeListener; 30d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kimimport android.media.AudioDevicePort; 31ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kimimport android.media.AudioFormat; 32d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kimimport android.media.AudioManager; 33d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kimimport android.media.AudioPatch; 34d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kimimport android.media.AudioPort; 35d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kimimport android.media.AudioPortConfig; 36d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputHardware; 37d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputHardwareCallback; 38d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.TvInputHardwareInfo; 39b2b3151a42bd563669b222b82efb64e294dc9049Jinsuk Kimimport android.media.tv.TvContract; 40969167dc05a6485a32d160895871cff46fd81884Wonsik Kimimport android.media.tv.TvInputInfo; 41d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.TvStreamConfig; 42969167dc05a6485a32d160895871cff46fd81884Wonsik Kimimport android.os.Handler; 43c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kimimport android.os.IBinder; 44969167dc05a6485a32d160895871cff46fd81884Wonsik Kimimport android.os.Looper; 45969167dc05a6485a32d160895871cff46fd81884Wonsik Kimimport android.os.Message; 46c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kimimport android.os.RemoteException; 477474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kimimport android.os.ServiceManager; 484f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Leeimport android.util.ArrayMap; 49c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kimimport android.util.Slog; 50c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kimimport android.util.SparseArray; 51969167dc05a6485a32d160895871cff46fd81884Wonsik Kimimport android.util.SparseBooleanArray; 52c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kimimport android.view.KeyEvent; 53c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kimimport android.view.Surface; 54c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 55969167dc05a6485a32d160895871cff46fd81884Wonsik Kimimport com.android.server.SystemService; 56969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 57c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kimimport java.util.ArrayList; 584f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Leeimport java.util.Collections; 59c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kimimport java.util.HashSet; 60d922a546b94119217fb790113d0001cad0432060Wonsik Kimimport java.util.Iterator; 61d922a546b94119217fb790113d0001cad0432060Wonsik Kimimport java.util.LinkedList; 62c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kimimport java.util.List; 634f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Leeimport java.util.Map; 64c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kimimport java.util.Set; 65c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 66c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim/** 67c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * A helper class for TvInputManagerService to handle TV input hardware. 68c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * 69c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * This class does a basic connection management and forwarding calls to TvInputHal which eventually 70c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * calls to tv_input HAL module. 71c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * 72c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * @hide 73c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim */ 747474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kimclass TvInputHardwareManager implements TvInputHal.Callback { 75c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private static final String TAG = TvInputHardwareManager.class.getSimpleName(); 764f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 774f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private final Context mContext; 784f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private final Listener mListener; 79c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private final TvInputHal mHal = new TvInputHal(this); 80d922a546b94119217fb790113d0001cad0432060Wonsik Kim private final SparseArray<Connection> mConnections = new SparseArray<>(); 81d922a546b94119217fb790113d0001cad0432060Wonsik Kim private final List<TvInputHardwareInfo> mHardwareList = new ArrayList<>(); 82d922a546b94119217fb790113d0001cad0432060Wonsik Kim private List<HdmiCecDeviceInfo> mHdmiCecDeviceList = new LinkedList<>(); 834f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee /* A map from a device ID to the matching TV input ID. */ 84d922a546b94119217fb790113d0001cad0432060Wonsik Kim private final SparseArray<String> mHardwareInputIdMap = new SparseArray<>(); 854f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee /* A map from a HDMI logical address to the matching TV input ID. */ 86d922a546b94119217fb790113d0001cad0432060Wonsik Kim private final SparseArray<String> mHdmiCecInputIdMap = new SparseArray<>(); 87d922a546b94119217fb790113d0001cad0432060Wonsik Kim private final Map<String, TvInputInfo> mInputMap = new ArrayMap<>(); 884f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 89d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim private final AudioManager mAudioManager; 904f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private IHdmiControlService mHdmiControlService; 917474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim private final IHdmiHotplugEventListener mHdmiHotplugEventListener = 927474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim new HdmiHotplugEventListener(); 934f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private final IHdmiDeviceEventListener mHdmiDeviceEventListener = new HdmiDeviceEventListener(); 947474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim private final IHdmiInputChangeListener mHdmiInputChangeListener = new HdmiInputChangeListener(); 95d922a546b94119217fb790113d0001cad0432060Wonsik Kim // TODO: Should handle STANDBY case. 964f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private final SparseBooleanArray mHdmiStateMap = new SparseBooleanArray(); 97d922a546b94119217fb790113d0001cad0432060Wonsik Kim private final List<Message> mPendingHdmiDeviceEvents = new LinkedList<>(); 98969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 99187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // Calls to mListener should happen here. 100187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final Handler mHandler = new ListenerHandler(); 101c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 102c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private final Object mLock = new Object(); 103c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 104187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public TvInputHardwareManager(Context context, Listener listener) { 105c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mContext = context; 106187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mListener = listener; 107d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 108c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mHal.init(); 109969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 110969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 111969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public void onBootPhase(int phase) { 112969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { 1134f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mHdmiControlService = IHdmiControlService.Stub.asInterface(ServiceManager.getService( 1144f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee Context.HDMI_CONTROL_SERVICE)); 1154f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (mHdmiControlService != null) { 1167474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim try { 1174f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mHdmiControlService.addHotplugEventListener(mHdmiHotplugEventListener); 1184f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mHdmiControlService.addDeviceEventListener(mHdmiDeviceEventListener); 119d922a546b94119217fb790113d0001cad0432060Wonsik Kim mHdmiCecDeviceList.addAll(mHdmiControlService.getInputDevices()); 1204f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mHdmiControlService.setInputChangeListener(mHdmiInputChangeListener); 1217474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim } catch (RemoteException e) { 1224f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee Slog.w(TAG, "Error registering listeners to HdmiControlService:", e); 1237474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim } 1247474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim } 125969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 126c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 127c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 128c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 1294f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void onDeviceAvailable(TvInputHardwareInfo info, TvStreamConfig[] configs) { 130c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim synchronized (mLock) { 131c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Connection connection = new Connection(info); 132c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim connection.updateConfigsLocked(configs); 133c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mConnections.put(info.getDeviceId(), connection); 134d922a546b94119217fb790113d0001cad0432060Wonsik Kim buildHardwareListLocked(); 135187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mHandler.obtainMessage( 136187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ListenerHandler.HARDWARE_DEVICE_ADDED, 0, 0, info).sendToTarget(); 137d922a546b94119217fb790113d0001cad0432060Wonsik Kim if (info.getType() == TvInputHardwareInfo.TV_INPUT_TYPE_HDMI) { 138d922a546b94119217fb790113d0001cad0432060Wonsik Kim processPendingHdmiDeviceEventsLocked(); 139d922a546b94119217fb790113d0001cad0432060Wonsik Kim } 140c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 141c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 142c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 143d922a546b94119217fb790113d0001cad0432060Wonsik Kim private void buildHardwareListLocked() { 144d922a546b94119217fb790113d0001cad0432060Wonsik Kim mHardwareList.clear(); 145c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim for (int i = 0; i < mConnections.size(); ++i) { 146d922a546b94119217fb790113d0001cad0432060Wonsik Kim mHardwareList.add(mConnections.valueAt(i).getHardwareInfoLocked()); 147c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 148c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 149c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 150c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 151c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public void onDeviceUnavailable(int deviceId) { 152c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim synchronized (mLock) { 153c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Connection connection = mConnections.get(deviceId); 154c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim if (connection == null) { 155c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Slog.e(TAG, "onDeviceUnavailable: Cannot find a connection with " + deviceId); 156c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return; 157c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 158969167dc05a6485a32d160895871cff46fd81884Wonsik Kim connection.resetLocked(null, null, null, null, null); 159c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mConnections.remove(deviceId); 160d922a546b94119217fb790113d0001cad0432060Wonsik Kim buildHardwareListLocked(); 1614f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee TvInputHardwareInfo info = connection.getHardwareInfoLocked(); 162d922a546b94119217fb790113d0001cad0432060Wonsik Kim if (info.getType() == TvInputHardwareInfo.TV_INPUT_TYPE_HDMI) { 163d922a546b94119217fb790113d0001cad0432060Wonsik Kim // Remove HDMI CEC devices linked with this hardware. 164d922a546b94119217fb790113d0001cad0432060Wonsik Kim for (Iterator<HdmiCecDeviceInfo> it = mHdmiCecDeviceList.iterator(); 165d922a546b94119217fb790113d0001cad0432060Wonsik Kim it.hasNext(); ) { 166d922a546b94119217fb790113d0001cad0432060Wonsik Kim HdmiCecDeviceInfo deviceInfo = it.next(); 167d922a546b94119217fb790113d0001cad0432060Wonsik Kim if (deviceInfo.getPortId() == info.getHdmiPortId()) { 168d922a546b94119217fb790113d0001cad0432060Wonsik Kim mHandler.obtainMessage(ListenerHandler.HDMI_CEC_DEVICE_REMOVED, 0, 0, 169d922a546b94119217fb790113d0001cad0432060Wonsik Kim deviceInfo).sendToTarget(); 170d922a546b94119217fb790113d0001cad0432060Wonsik Kim it.remove(); 171d922a546b94119217fb790113d0001cad0432060Wonsik Kim } 172d922a546b94119217fb790113d0001cad0432060Wonsik Kim } 173d922a546b94119217fb790113d0001cad0432060Wonsik Kim } 174187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mHandler.obtainMessage( 1754f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ListenerHandler.HARDWARE_DEVICE_REMOVED, 0, 0, info).sendToTarget(); 176c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 177c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 178c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 179c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 180c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public void onStreamConfigurationChanged(int deviceId, TvStreamConfig[] configs) { 181c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim synchronized (mLock) { 182c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Connection connection = mConnections.get(deviceId); 183c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim if (connection == null) { 184c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Slog.e(TAG, "StreamConfigurationChanged: Cannot find a connection with " 185c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim + deviceId); 186c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return; 187c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 188c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim connection.updateConfigsLocked(configs); 189c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 190c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim connection.getCallbackLocked().onStreamConfigChanged(configs); 191c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } catch (RemoteException e) { 1924f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee Slog.e(TAG, "error in onStreamConfigurationChanged", e); 193c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 194c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 195c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 196c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 197c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo @Override 198c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo public void onFirstFrameCaptured(int deviceId, int streamId) { 199c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo synchronized (mLock) { 200c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Connection connection = mConnections.get(deviceId); 201c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (connection == null) { 202c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Slog.e(TAG, "FirstFrameCaptured: Cannot find a connection with " 203c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo + deviceId); 204c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return; 205c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 206c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Runnable runnable = connection.getOnFirstFrameCapturedLocked(); 207c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (runnable != null) { 208c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo runnable.run(); 209c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo connection.setOnFirstFrameCapturedLocked(null); 210c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 211c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 212c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 213c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 214c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public List<TvInputHardwareInfo> getHardwareList() { 215c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim synchronized (mLock) { 216d922a546b94119217fb790113d0001cad0432060Wonsik Kim return Collections.unmodifiableList(mHardwareList); 217c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 218c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 219c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 2204f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public List<HdmiCecDeviceInfo> getHdmiCecInputDeviceList() { 221d922a546b94119217fb790113d0001cad0432060Wonsik Kim synchronized (mLock) { 222d922a546b94119217fb790113d0001cad0432060Wonsik Kim return Collections.unmodifiableList(mHdmiCecDeviceList); 2234f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 2244f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 2254f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 226e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim private boolean checkUidChangedLocked( 227e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim Connection connection, int callingUid, int resolvedUserId) { 228e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim Integer connectionCallingUid = connection.getCallingUidLocked(); 229e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim Integer connectionResolvedUserId = connection.getResolvedUserIdLocked(); 230e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim if (connectionCallingUid == null || connectionResolvedUserId == null) { 231e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim return true; 232e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim } 233e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim if (connectionCallingUid != callingUid || connectionResolvedUserId != resolvedUserId) { 234e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim return true; 235e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim } 236e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim return false; 237e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim } 238e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim 239969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private int convertConnectedToState(boolean connected) { 240969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (connected) { 241969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return INPUT_STATE_CONNECTED; 242969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } else { 243969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return INPUT_STATE_DISCONNECTED; 244969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 245969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 246969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 2474f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void addHardwareTvInput(int deviceId, TvInputInfo info) { 248969167dc05a6485a32d160895871cff46fd81884Wonsik Kim synchronized (mLock) { 2494f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee String oldInputId = mHardwareInputIdMap.get(deviceId); 2504f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (oldInputId != null) { 251969167dc05a6485a32d160895871cff46fd81884Wonsik Kim Slog.w(TAG, "Trying to override previous registration: old = " 2524f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee + mInputMap.get(oldInputId) + ":" + deviceId + ", new = " 253969167dc05a6485a32d160895871cff46fd81884Wonsik Kim + info + ":" + deviceId); 254969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 2554f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mHardwareInputIdMap.put(deviceId, info.getId()); 2564f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mInputMap.put(info.getId(), info); 257969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 258969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (int i = 0; i < mHdmiStateMap.size(); ++i) { 259d922a546b94119217fb790113d0001cad0432060Wonsik Kim TvInputHardwareInfo hardwareInfo = 260d922a546b94119217fb790113d0001cad0432060Wonsik Kim findHardwareInfoForHdmiPortLocked(mHdmiStateMap.keyAt(i)); 261d922a546b94119217fb790113d0001cad0432060Wonsik Kim if (hardwareInfo == null) { 262d922a546b94119217fb790113d0001cad0432060Wonsik Kim continue; 263d922a546b94119217fb790113d0001cad0432060Wonsik Kim } 264d922a546b94119217fb790113d0001cad0432060Wonsik Kim String inputId = mHardwareInputIdMap.get(hardwareInfo.getDeviceId()); 265969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (inputId != null && inputId.equals(info.getId())) { 266187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mHandler.obtainMessage(ListenerHandler.STATE_CHANGED, 267969167dc05a6485a32d160895871cff46fd81884Wonsik Kim convertConnectedToState(mHdmiStateMap.valueAt(i)), 0, 268969167dc05a6485a32d160895871cff46fd81884Wonsik Kim inputId).sendToTarget(); 269969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 270969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 271969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 272969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 273969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 27438feae971c43700c9cb15aafbf8bd37340675a50Wonsik Kim private static <T> int indexOfEqualValue(SparseArray<T> map, T value) { 27538feae971c43700c9cb15aafbf8bd37340675a50Wonsik Kim for (int i = 0; i < map.size(); ++i) { 27638feae971c43700c9cb15aafbf8bd37340675a50Wonsik Kim if (map.valueAt(i).equals(value)) { 27738feae971c43700c9cb15aafbf8bd37340675a50Wonsik Kim return i; 27838feae971c43700c9cb15aafbf8bd37340675a50Wonsik Kim } 27938feae971c43700c9cb15aafbf8bd37340675a50Wonsik Kim } 28038feae971c43700c9cb15aafbf8bd37340675a50Wonsik Kim return -1; 28138feae971c43700c9cb15aafbf8bd37340675a50Wonsik Kim } 28238feae971c43700c9cb15aafbf8bd37340675a50Wonsik Kim 2834f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void addHdmiCecTvInput(int logicalAddress, TvInputInfo info) { 2844f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (info.getType() != TvInputInfo.TYPE_HDMI) { 2854f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee throw new IllegalArgumentException("info (" + info + ") has non-HDMI type."); 2864f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 2874f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee synchronized (mLock) { 2884f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee String parentId = info.getParentId(); 28938feae971c43700c9cb15aafbf8bd37340675a50Wonsik Kim int parentIndex = indexOfEqualValue(mHardwareInputIdMap, parentId); 29038feae971c43700c9cb15aafbf8bd37340675a50Wonsik Kim if (parentIndex < 0) { 2914f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee throw new IllegalArgumentException("info (" + info + ") has invalid parentId."); 2924f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 2934f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee String oldInputId = mHdmiCecInputIdMap.get(logicalAddress); 2944f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (oldInputId != null) { 2954f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee Slog.w(TAG, "Trying to override previous registration: old = " 2964f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee + mInputMap.get(oldInputId) + ":" + logicalAddress + ", new = " 2974f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee + info + ":" + logicalAddress); 2984f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 2994f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mHdmiCecInputIdMap.put(logicalAddress, info.getId()); 3004f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mInputMap.put(info.getId(), info); 3014f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 3024f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 3034f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 3044f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void removeTvInput(String inputId) { 3054f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee synchronized (mLock) { 3064f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mInputMap.remove(inputId); 30738feae971c43700c9cb15aafbf8bd37340675a50Wonsik Kim int hardwareIndex = indexOfEqualValue(mHardwareInputIdMap, inputId); 3084f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (hardwareIndex >= 0) { 3094f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mHardwareInputIdMap.removeAt(hardwareIndex); 3104f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 31138feae971c43700c9cb15aafbf8bd37340675a50Wonsik Kim int cecIndex = indexOfEqualValue(mHdmiCecInputIdMap, inputId); 3124f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (cecIndex >= 0) { 3134f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mHdmiCecInputIdMap.removeAt(cecIndex); 3144f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 3154f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 3164f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 3174f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 318c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim /** 319c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * Create a TvInputHardware object with a specific deviceId. One service at a time can access 320c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * the object, and if more than one process attempts to create hardware with the same deviceId, 321c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * the latest service will get the object and all the other hardware are released. The 322c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * release is notified via ITvInputHardwareCallback.onReleased(). 323c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim */ 324c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public ITvInputHardware acquireHardware(int deviceId, ITvInputHardwareCallback callback, 325969167dc05a6485a32d160895871cff46fd81884Wonsik Kim TvInputInfo info, int callingUid, int resolvedUserId) { 326c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim if (callback == null) { 327c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim throw new NullPointerException(); 328c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 329c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim synchronized (mLock) { 330c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Connection connection = mConnections.get(deviceId); 331c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim if (connection == null) { 332c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Slog.e(TAG, "Invalid deviceId : " + deviceId); 333c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return null; 334c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 335e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim if (checkUidChangedLocked(connection, callingUid, resolvedUserId)) { 336969167dc05a6485a32d160895871cff46fd81884Wonsik Kim TvInputHardwareImpl hardware = 337969167dc05a6485a32d160895871cff46fd81884Wonsik Kim new TvInputHardwareImpl(connection.getHardwareInfoLocked()); 338c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 339c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim callback.asBinder().linkToDeath(connection, 0); 340c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } catch (RemoteException e) { 341c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim hardware.release(); 342c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return null; 343c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 344969167dc05a6485a32d160895871cff46fd81884Wonsik Kim connection.resetLocked(hardware, callback, info, callingUid, resolvedUserId); 345c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 346c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return connection.getHardwareLocked(); 347c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 348c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 349c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 350c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim /** 351c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * Release the specified hardware. 352c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim */ 353c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public void releaseHardware(int deviceId, ITvInputHardware hardware, int callingUid, 354c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim int resolvedUserId) { 355c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim synchronized (mLock) { 356c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Connection connection = mConnections.get(deviceId); 357c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim if (connection == null) { 358c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Slog.e(TAG, "Invalid deviceId : " + deviceId); 359c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return; 360c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 361c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim if (connection.getHardwareLocked() != hardware 362e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim || checkUidChangedLocked(connection, callingUid, resolvedUserId)) { 363c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return; 364c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 365969167dc05a6485a32d160895871cff46fd81884Wonsik Kim connection.resetLocked(null, null, null, null, null); 366969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 367969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 368969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 369d922a546b94119217fb790113d0001cad0432060Wonsik Kim private TvInputHardwareInfo findHardwareInfoForHdmiPortLocked(int port) { 370d922a546b94119217fb790113d0001cad0432060Wonsik Kim for (TvInputHardwareInfo hardwareInfo : mHardwareList) { 371969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (hardwareInfo.getType() == TvInputHardwareInfo.TV_INPUT_TYPE_HDMI 372969167dc05a6485a32d160895871cff46fd81884Wonsik Kim && hardwareInfo.getHdmiPortId() == port) { 373d922a546b94119217fb790113d0001cad0432060Wonsik Kim return hardwareInfo; 374969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 375969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 376969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return null; 377969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 378969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 379c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo private int findDeviceIdForInputIdLocked(String inputId) { 380c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo for (int i = 0; i < mConnections.size(); ++i) { 381c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Connection connection = mConnections.get(i); 382c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (connection.getInfoLocked().getId().equals(inputId)) { 383c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return i; 384c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 385c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 386c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return -1; 387c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 388c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 389c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo /** 390c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo * Get the list of TvStreamConfig which is buffered mode. 391c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo */ 392c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo public List<TvStreamConfig> getAvailableTvStreamConfigList(String inputId, int callingUid, 393c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo int resolvedUserId) { 394c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo List<TvStreamConfig> configsList = new ArrayList<TvStreamConfig>(); 395c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo synchronized (mLock) { 396c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo int deviceId = findDeviceIdForInputIdLocked(inputId); 397c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (deviceId < 0) { 398c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Slog.e(TAG, "Invalid inputId : " + inputId); 399c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return configsList; 400c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 401c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Connection connection = mConnections.get(deviceId); 402c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo for (TvStreamConfig config : connection.getConfigsLocked()) { 403c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (config.getType() == TvStreamConfig.STREAM_TYPE_BUFFER_PRODUCER) { 404c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo configsList.add(config); 405c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 406c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 407c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 408c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return configsList; 409c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 410c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 411c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo /** 412c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo * Take a snapshot of the given TV input into the provided Surface. 413c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo */ 414c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo public boolean captureFrame(String inputId, Surface surface, final TvStreamConfig config, 415c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo int callingUid, int resolvedUserId) { 416c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo synchronized (mLock) { 417c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo int deviceId = findDeviceIdForInputIdLocked(inputId); 418c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (deviceId < 0) { 419c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Slog.e(TAG, "Invalid inputId : " + inputId); 420c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return false; 421c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 422c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Connection connection = mConnections.get(deviceId); 423c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final TvInputHardwareImpl hardwareImpl = connection.getHardwareImplLocked(); 424c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (hardwareImpl != null) { 425c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo // Stop previous capture. 426c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Runnable runnable = connection.getOnFirstFrameCapturedLocked(); 427c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (runnable != null) { 428c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo runnable.run(); 429c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo connection.setOnFirstFrameCapturedLocked(null); 430c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 431c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 432c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo boolean result = hardwareImpl.startCapture(surface, config); 433c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (result) { 434c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo connection.setOnFirstFrameCapturedLocked(new Runnable() { 435c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo @Override 436c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo public void run() { 437c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo hardwareImpl.stopCapture(config); 438c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 439c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo }); 440c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 441c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return result; 442c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 443c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 444c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return false; 445c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 446c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 447d922a546b94119217fb790113d0001cad0432060Wonsik Kim private void processPendingHdmiDeviceEventsLocked() { 448d922a546b94119217fb790113d0001cad0432060Wonsik Kim for (Iterator<Message> it = mPendingHdmiDeviceEvents.iterator(); it.hasNext(); ) { 449d922a546b94119217fb790113d0001cad0432060Wonsik Kim Message msg = it.next(); 450d922a546b94119217fb790113d0001cad0432060Wonsik Kim HdmiCecDeviceInfo deviceInfo = (HdmiCecDeviceInfo) msg.obj; 451d922a546b94119217fb790113d0001cad0432060Wonsik Kim TvInputHardwareInfo hardwareInfo = 452d922a546b94119217fb790113d0001cad0432060Wonsik Kim findHardwareInfoForHdmiPortLocked(deviceInfo.getPortId()); 453d922a546b94119217fb790113d0001cad0432060Wonsik Kim if (hardwareInfo != null) { 454d922a546b94119217fb790113d0001cad0432060Wonsik Kim msg.sendToTarget(); 455d922a546b94119217fb790113d0001cad0432060Wonsik Kim it.remove(); 456d922a546b94119217fb790113d0001cad0432060Wonsik Kim } 457d922a546b94119217fb790113d0001cad0432060Wonsik Kim } 458d922a546b94119217fb790113d0001cad0432060Wonsik Kim } 459d922a546b94119217fb790113d0001cad0432060Wonsik Kim 460c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private class Connection implements IBinder.DeathRecipient { 461969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private final TvInputHardwareInfo mHardwareInfo; 462969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private TvInputInfo mInfo; 463c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private TvInputHardwareImpl mHardware = null; 464c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private ITvInputHardwareCallback mCallback; 465c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private TvStreamConfig[] mConfigs = null; 466c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private Integer mCallingUid = null; 467c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private Integer mResolvedUserId = null; 468c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo private Runnable mOnFirstFrameCaptured; 469c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 470969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public Connection(TvInputHardwareInfo hardwareInfo) { 471969167dc05a6485a32d160895871cff46fd81884Wonsik Kim mHardwareInfo = hardwareInfo; 472c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 473c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 474c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim // *Locked methods assume TvInputHardwareManager.mLock is held. 475c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 476969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public void resetLocked(TvInputHardwareImpl hardware, ITvInputHardwareCallback callback, 477969167dc05a6485a32d160895871cff46fd81884Wonsik Kim TvInputInfo info, Integer callingUid, Integer resolvedUserId) { 478c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim if (mHardware != null) { 479c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 480c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mCallback.onReleased(); 481c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } catch (RemoteException e) { 4824f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee Slog.e(TAG, "error in Connection::resetLocked", e); 483c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 484c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mHardware.release(); 485c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 486c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mHardware = hardware; 487c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mCallback = callback; 488969167dc05a6485a32d160895871cff46fd81884Wonsik Kim mInfo = info; 489c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mCallingUid = callingUid; 490c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mResolvedUserId = resolvedUserId; 491c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo mOnFirstFrameCaptured = null; 492c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 493c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim if (mHardware != null && mCallback != null) { 494c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 495c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mCallback.onStreamConfigChanged(getConfigsLocked()); 496c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } catch (RemoteException e) { 4974f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee Slog.e(TAG, "error in Connection::resetLocked", e); 498c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 499c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 500c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 501c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 502c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public void updateConfigsLocked(TvStreamConfig[] configs) { 503c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mConfigs = configs; 504c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 505c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 506969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public TvInputHardwareInfo getHardwareInfoLocked() { 507969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return mHardwareInfo; 508969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 509969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 510969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public TvInputInfo getInfoLocked() { 511c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return mInfo; 512c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 513c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 514c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public ITvInputHardware getHardwareLocked() { 515c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return mHardware; 516c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 517c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 518c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo public TvInputHardwareImpl getHardwareImplLocked() { 519c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return mHardware; 520c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 521c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 522c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public ITvInputHardwareCallback getCallbackLocked() { 523c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return mCallback; 524c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 525c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 526c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public TvStreamConfig[] getConfigsLocked() { 527c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return mConfigs; 528c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 529c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 530e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim public Integer getCallingUidLocked() { 531c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return mCallingUid; 532c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 533c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 534e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim public Integer getResolvedUserIdLocked() { 535c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return mResolvedUserId; 536c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 537c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 538c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo public void setOnFirstFrameCapturedLocked(Runnable runnable) { 539c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo mOnFirstFrameCaptured = runnable; 540c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 541c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 542c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo public Runnable getOnFirstFrameCapturedLocked() { 543c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return mOnFirstFrameCaptured; 544c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 545c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 546c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 547c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public void binderDied() { 548c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim synchronized (mLock) { 549969167dc05a6485a32d160895871cff46fd81884Wonsik Kim resetLocked(null, null, null, null, null); 550c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 551c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 552c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 553c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 554c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private class TvInputHardwareImpl extends ITvInputHardware.Stub { 555c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private final TvInputHardwareInfo mInfo; 556c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private boolean mReleased = false; 557c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private final Object mImplLock = new Object(); 558c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 559d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim private final AudioDevicePort mAudioSource; 560ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim private AudioDevicePort mAudioSink; 561d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim private AudioPatch mAudioPatch = null; 562d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim 563839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim private TvStreamConfig mActiveConfig = null; 564839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim 565ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim private int mDesiredSamplingRate = 0; 566ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim private int mDesiredChannelMask = AudioFormat.CHANNEL_OUT_DEFAULT; 567ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim private int mDesiredFormat = AudioFormat.ENCODING_DEFAULT; 568ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim 569c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public TvInputHardwareImpl(TvInputHardwareInfo info) { 570c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mInfo = info; 571d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim AudioDevicePort audioSource = null; 572d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim if (mInfo.getAudioType() != AudioManager.DEVICE_NONE) { 573ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim audioSource = findAudioDevicePort(mInfo.getAudioType(), mInfo.getAudioAddress()); 574ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim mAudioSink = findAudioSinkFromAudioPolicy(); 575ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim } 576ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim mAudioSource = audioSource; 577ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim } 578ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim 579ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim private AudioDevicePort findAudioSinkFromAudioPolicy() { 580ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim ArrayList<AudioPort> devicePorts = new ArrayList<AudioPort>(); 581ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim if (mAudioManager.listAudioDevicePorts(devicePorts) == AudioManager.SUCCESS) { 582ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim int sinkDevice = mAudioManager.getDevicesForStream(AudioManager.STREAM_MUSIC); 583ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim for (AudioPort port : devicePorts) { 584ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim AudioDevicePort devicePort = (AudioDevicePort) port; 585ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim if (devicePort.type() == sinkDevice) { 586ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim return devicePort; 587d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim } 588d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim } 589d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim } 590ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim return null; 591ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim } 592ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim 593ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim private AudioDevicePort findAudioDevicePort(int type, String address) { 594ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim if (type == AudioManager.DEVICE_NONE) { 595ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim return null; 596ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim } 597ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim ArrayList<AudioPort> devicePorts = new ArrayList<AudioPort>(); 598ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim if (mAudioManager.listAudioDevicePorts(devicePorts) != AudioManager.SUCCESS) { 599ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim return null; 600ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim } 601ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim for (AudioPort port : devicePorts) { 602ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim AudioDevicePort devicePort = (AudioDevicePort) port; 603ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim if (devicePort.type() == type && devicePort.address().equals(address)) { 604ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim return devicePort; 605ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim } 606ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim } 607ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim return null; 608c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 609c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 610c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public void release() { 611c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim synchronized (mImplLock) { 612d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim if (mAudioPatch != null) { 613d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim mAudioManager.releaseAudioPatch(mAudioPatch); 614d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim mAudioPatch = null; 615d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim } 616c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mReleased = true; 617c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 618c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 619c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 620839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim // A TvInputHardwareImpl object holds only one active session. Therefore, if a client 621839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim // attempts to call setSurface with different TvStreamConfig objects, the last call will 622839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim // prevail. 623c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 624c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public boolean setSurface(Surface surface, TvStreamConfig config) 625c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim throws RemoteException { 626c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim synchronized (mImplLock) { 627c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim if (mReleased) { 628c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim throw new IllegalStateException("Device already released."); 629c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 630839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim if (surface != null && config == null) { 631839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim return false; 632839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim } 633839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim if (surface == null && mActiveConfig == null) { 634839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim return false; 635839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim } 636d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim if (mAudioSource != null && mAudioSink != null) { 637d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim if (surface != null) { 638ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim updateAudioPatchLocked(); 639d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim } else { 640d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim mAudioManager.releaseAudioPatch(mAudioPatch); 641d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim mAudioPatch = null; 642d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim } 643d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim } 644839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim int result = TvInputHal.ERROR_UNKNOWN; 645839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim if (surface == null) { 646839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim result = mHal.removeStream(mInfo.getDeviceId(), mActiveConfig); 647839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim mActiveConfig = null; 648839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim } else { 649839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim if (config != mActiveConfig && mActiveConfig != null) { 650839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim result = mHal.removeStream(mInfo.getDeviceId(), mActiveConfig); 651839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim if (result != TvInputHal.SUCCESS) { 652839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim mActiveConfig = null; 653839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim return false; 654839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim } 655839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim } 656839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim result = mHal.addStream(mInfo.getDeviceId(), surface, config); 657839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim if (result == TvInputHal.SUCCESS) { 658839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim mActiveConfig = config; 659839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim } 660839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim } 661839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim return result == TvInputHal.SUCCESS; 662c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 663c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 664c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 665ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim private void updateAudioPatchLocked() { 666ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim AudioPortConfig sourceConfig = mAudioSource.activeConfig(); 667ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim AudioPortConfig sinkConfig = mAudioSink.activeConfig(); 668ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim AudioPatch[] audioPatchArray = new AudioPatch[] { mAudioPatch }; 669ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim if (sinkConfig == null 670ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim || (mDesiredSamplingRate != 0 671ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim && sinkConfig.samplingRate() != mDesiredSamplingRate) 672ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim || (mDesiredChannelMask != AudioFormat.CHANNEL_OUT_DEFAULT 673ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim && sinkConfig.channelMask() != mDesiredChannelMask) 674ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim || (mDesiredFormat != AudioFormat.ENCODING_DEFAULT 675ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim && sinkConfig.format() != mDesiredFormat)) { 676ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim sinkConfig = mAudioSource.buildConfig(mDesiredSamplingRate, mDesiredChannelMask, 677ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim mDesiredFormat, null); 678ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim } 679ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim if (sourceConfig == null) { 680ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim sourceConfig = mAudioSource.buildConfig(sinkConfig.samplingRate(), 681ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim sinkConfig.channelMask(), sinkConfig.format(), null); 682ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim } 683ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim mAudioManager.createAudioPatch( 684ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim audioPatchArray, 685ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim new AudioPortConfig[] { sourceConfig }, 686ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim new AudioPortConfig[] { sinkConfig }); 687ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim mAudioPatch = audioPatchArray[0]; 688ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim } 689ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim 690c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 691c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public void setVolume(float volume) throws RemoteException { 692c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim synchronized (mImplLock) { 693c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim if (mReleased) { 694c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim throw new IllegalStateException("Device already released."); 695c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 696c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 697d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim // TODO: Use AudioGain? 698c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 699c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 700c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 701c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public boolean dispatchKeyEventToHdmi(KeyEvent event) throws RemoteException { 702c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim synchronized (mImplLock) { 703c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim if (mReleased) { 704c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim throw new IllegalStateException("Device already released."); 705c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 706c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 707610ccd9117fc1611fcc576d1cb1f717f1ef3fcbfWonsik Kim if (mInfo.getType() != TvInputHardwareInfo.TV_INPUT_TYPE_HDMI) { 708c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return false; 709c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 710c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim // TODO(hdmi): mHdmiClient.sendKeyEvent(event); 711c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return false; 712c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 713c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 714c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo private boolean startCapture(Surface surface, TvStreamConfig config) { 715c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo synchronized (mImplLock) { 716c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (mReleased) { 717c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return false; 718c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 719c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (surface == null || config == null) { 720c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return false; 721c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 722c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (config.getType() != TvStreamConfig.STREAM_TYPE_BUFFER_PRODUCER) { 723c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return false; 724c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 725c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 726c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo int result = mHal.addStream(mInfo.getDeviceId(), surface, config); 727c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return result == TvInputHal.SUCCESS; 728c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 729c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 730c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 731c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo private boolean stopCapture(TvStreamConfig config) { 732c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo synchronized (mImplLock) { 733c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (mReleased) { 734c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return false; 735c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 736c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (config == null) { 737c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return false; 738c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 739c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 740c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo int result = mHal.removeStream(mInfo.getDeviceId(), config); 741c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return result == TvInputHal.SUCCESS; 742c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 743c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 744ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim 745ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim @Override 746ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim public void overrideAudioSink(int audioType, String audioAddress, int samplingRate, 747ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim int channelMask, int format) { 748ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim synchronized (mImplLock) { 749ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim if (audioType == AudioManager.DEVICE_NONE) { 750ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim mAudioSink = findAudioSinkFromAudioPolicy(); 751ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim } else { 752ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim AudioDevicePort audioSink = findAudioDevicePort(audioType, audioAddress); 753ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim if (audioSink != null) { 754ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim mAudioSink = audioSink; 755ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim } 756ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim } 757ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim mDesiredSamplingRate = samplingRate; 758ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim mDesiredChannelMask = channelMask; 759ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim mDesiredFormat = format; 760ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim 761ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim if (mAudioPatch != null) { 762ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim updateAudioPatchLocked(); 763ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim } 764ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim } 765ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim } 766c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 767969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 768187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim interface Listener { 769187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void onStateChanged(String inputId, int state); 770187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void onHardwareDeviceAdded(TvInputHardwareInfo info); 7714f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void onHardwareDeviceRemoved(TvInputHardwareInfo info); 772187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void onHdmiCecDeviceAdded(HdmiCecDeviceInfo cecDevice); 773187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void onHdmiCecDeviceRemoved(HdmiCecDeviceInfo cecDevice); 774187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 775969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 776187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private class ListenerHandler extends Handler { 777187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private static final int STATE_CHANGED = 1; 778187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private static final int HARDWARE_DEVICE_ADDED = 2; 779187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private static final int HARDWARE_DEVICE_REMOVED = 3; 7804f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private static final int HDMI_CEC_DEVICE_ADDED = 4; 7814f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private static final int HDMI_CEC_DEVICE_REMOVED = 5; 782969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 783969167dc05a6485a32d160895871cff46fd81884Wonsik Kim @Override 784969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public final void handleMessage(Message msg) { 785969167dc05a6485a32d160895871cff46fd81884Wonsik Kim switch (msg.what) { 786187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim case STATE_CHANGED: { 787969167dc05a6485a32d160895871cff46fd81884Wonsik Kim String inputId = (String) msg.obj; 788969167dc05a6485a32d160895871cff46fd81884Wonsik Kim int state = msg.arg1; 789187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mListener.onStateChanged(inputId, state); 790187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim break; 791187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 792187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim case HARDWARE_DEVICE_ADDED: { 793187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim TvInputHardwareInfo info = (TvInputHardwareInfo) msg.obj; 794187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mListener.onHardwareDeviceAdded(info); 795187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim break; 796187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 797187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim case HARDWARE_DEVICE_REMOVED: { 7984f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee TvInputHardwareInfo info = (TvInputHardwareInfo) msg.obj; 7994f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mListener.onHardwareDeviceRemoved(info); 800187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim break; 801187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 8024f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee case HDMI_CEC_DEVICE_ADDED: { 803187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim HdmiCecDeviceInfo info = (HdmiCecDeviceInfo) msg.obj; 804187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mListener.onHdmiCecDeviceAdded(info); 805187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim break; 806187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 8074f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee case HDMI_CEC_DEVICE_REMOVED: { 808187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim HdmiCecDeviceInfo info = (HdmiCecDeviceInfo) msg.obj; 809187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mListener.onHdmiCecDeviceRemoved(info); 810969167dc05a6485a32d160895871cff46fd81884Wonsik Kim break; 811969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 812969167dc05a6485a32d160895871cff46fd81884Wonsik Kim default: { 813969167dc05a6485a32d160895871cff46fd81884Wonsik Kim Slog.w(TAG, "Unhandled message: " + msg); 814969167dc05a6485a32d160895871cff46fd81884Wonsik Kim break; 815969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 816969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 817969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 818969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 819187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 8207474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim // Listener implementations for HdmiControlService 8217474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim 8227474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim private final class HdmiHotplugEventListener extends IHdmiHotplugEventListener.Stub { 8237474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim @Override 8247474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim public void onReceived(HdmiHotplugEvent event) { 8257474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim synchronized (mLock) { 8267474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim mHdmiStateMap.put(event.getPort(), event.isConnected()); 827d922a546b94119217fb790113d0001cad0432060Wonsik Kim TvInputHardwareInfo hardwareInfo = 828d922a546b94119217fb790113d0001cad0432060Wonsik Kim findHardwareInfoForHdmiPortLocked(event.getPort()); 829d922a546b94119217fb790113d0001cad0432060Wonsik Kim if (hardwareInfo == null) { 830d922a546b94119217fb790113d0001cad0432060Wonsik Kim return; 831d922a546b94119217fb790113d0001cad0432060Wonsik Kim } 832d922a546b94119217fb790113d0001cad0432060Wonsik Kim String inputId = mHardwareInputIdMap.get(hardwareInfo.getDeviceId()); 8337474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim if (inputId == null) { 8347474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim return; 8357474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim } 8367474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim mHandler.obtainMessage(ListenerHandler.STATE_CHANGED, 8377474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim convertConnectedToState(event.isConnected()), 0, inputId).sendToTarget(); 8387474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim } 8397474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim } 8407474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim } 8417474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim 842187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final class HdmiDeviceEventListener extends IHdmiDeviceEventListener.Stub { 843187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 844187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void onStatusChanged(HdmiCecDeviceInfo deviceInfo, boolean activated) { 845d922a546b94119217fb790113d0001cad0432060Wonsik Kim synchronized (mLock) { 846d922a546b94119217fb790113d0001cad0432060Wonsik Kim if (activated) { 847d922a546b94119217fb790113d0001cad0432060Wonsik Kim if (!mHdmiCecDeviceList.contains(deviceInfo)) { 848d922a546b94119217fb790113d0001cad0432060Wonsik Kim mHdmiCecDeviceList.add(deviceInfo); 849d922a546b94119217fb790113d0001cad0432060Wonsik Kim } else { 850d922a546b94119217fb790113d0001cad0432060Wonsik Kim Slog.w(TAG, "The list already contains " + deviceInfo + "; ignoring."); 851d922a546b94119217fb790113d0001cad0432060Wonsik Kim return; 852d922a546b94119217fb790113d0001cad0432060Wonsik Kim } 853d922a546b94119217fb790113d0001cad0432060Wonsik Kim } else { 854d922a546b94119217fb790113d0001cad0432060Wonsik Kim if (!mHdmiCecDeviceList.remove(deviceInfo)) { 855d922a546b94119217fb790113d0001cad0432060Wonsik Kim Slog.w(TAG, "The list doesn't contain " + deviceInfo + "; ignoring."); 856d922a546b94119217fb790113d0001cad0432060Wonsik Kim return; 857d922a546b94119217fb790113d0001cad0432060Wonsik Kim } 858d922a546b94119217fb790113d0001cad0432060Wonsik Kim } 859d922a546b94119217fb790113d0001cad0432060Wonsik Kim Message msg = mHandler.obtainMessage( 860d922a546b94119217fb790113d0001cad0432060Wonsik Kim activated ? ListenerHandler.HDMI_CEC_DEVICE_ADDED 861d922a546b94119217fb790113d0001cad0432060Wonsik Kim : ListenerHandler.HDMI_CEC_DEVICE_REMOVED, 862d922a546b94119217fb790113d0001cad0432060Wonsik Kim 0, 0, deviceInfo); 863d922a546b94119217fb790113d0001cad0432060Wonsik Kim if (findHardwareInfoForHdmiPortLocked(deviceInfo.getPortId()) != null) { 864d922a546b94119217fb790113d0001cad0432060Wonsik Kim msg.sendToTarget(); 865d922a546b94119217fb790113d0001cad0432060Wonsik Kim } else { 866d922a546b94119217fb790113d0001cad0432060Wonsik Kim mPendingHdmiDeviceEvents.add(msg); 867d922a546b94119217fb790113d0001cad0432060Wonsik Kim } 868d922a546b94119217fb790113d0001cad0432060Wonsik Kim } 869187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 870187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 8717474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim 8727474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim private final class HdmiInputChangeListener extends IHdmiInputChangeListener.Stub { 8737474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim @Override 8747474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim public void onChanged(HdmiCecDeviceInfo device) throws RemoteException { 875b2b3151a42bd563669b222b82efb64e294dc9049Jinsuk Kim String inputId; 876b2b3151a42bd563669b222b82efb64e294dc9049Jinsuk Kim synchronized (mLock) { 877b2b3151a42bd563669b222b82efb64e294dc9049Jinsuk Kim if (device.isCecDevice()) { 878b2b3151a42bd563669b222b82efb64e294dc9049Jinsuk Kim inputId = mHdmiCecInputIdMap.get(device.getLogicalAddress()); 879b2b3151a42bd563669b222b82efb64e294dc9049Jinsuk Kim } else { 880d922a546b94119217fb790113d0001cad0432060Wonsik Kim TvInputHardwareInfo hardwareInfo = 881d922a546b94119217fb790113d0001cad0432060Wonsik Kim findHardwareInfoForHdmiPortLocked(device.getPortId()); 882d922a546b94119217fb790113d0001cad0432060Wonsik Kim inputId = (hardwareInfo == null) ? null 883d922a546b94119217fb790113d0001cad0432060Wonsik Kim : mHardwareInputIdMap.get(hardwareInfo.getDeviceId()); 884b2b3151a42bd563669b222b82efb64e294dc9049Jinsuk Kim } 885b2b3151a42bd563669b222b82efb64e294dc9049Jinsuk Kim } 886b2b3151a42bd563669b222b82efb64e294dc9049Jinsuk Kim if (inputId != null) { 887b2b3151a42bd563669b222b82efb64e294dc9049Jinsuk Kim Intent intent = new Intent(Intent.ACTION_VIEW); 888b2b3151a42bd563669b222b82efb64e294dc9049Jinsuk Kim intent.setData(TvContract.buildChannelUriForPassthroughTvInput(inputId)); 889b2b3151a42bd563669b222b82efb64e294dc9049Jinsuk Kim mContext.startActivity(intent); 890b2b3151a42bd563669b222b82efb64e294dc9049Jinsuk Kim } else { 891b2b3151a42bd563669b222b82efb64e294dc9049Jinsuk Kim Slog.w(TAG, "onChanged: InputId cannot be found for :" + device); 892b2b3151a42bd563669b222b82efb64e294dc9049Jinsuk Kim } 8937474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim } 8947474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim } 895c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim} 896