TvInputHardwareManager.java revision 102670f16a44d4b25d7e3a252bedee0208b68c55
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; 2361daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jangimport android.hardware.hdmi.HdmiControlManager; 2461f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jangimport android.hardware.hdmi.HdmiDeviceInfo; 25969167dc05a6485a32d160895871cff46fd81884Wonsik Kimimport android.hardware.hdmi.HdmiHotplugEvent; 267474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kimimport android.hardware.hdmi.IHdmiControlService; 27187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kimimport android.hardware.hdmi.IHdmiDeviceEventListener; 287474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kimimport android.hardware.hdmi.IHdmiHotplugEventListener; 291f819bbfc80f0ae9de120e9b81250db36629a0b1Jungshik Jangimport android.hardware.hdmi.IHdmiSystemAudioModeChangeListener; 30d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kimimport android.media.AudioDevicePort; 31ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kimimport android.media.AudioFormat; 328e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kimimport android.media.AudioGain; 338e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kimimport android.media.AudioGainConfig; 34d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kimimport android.media.AudioManager; 35d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kimimport android.media.AudioPatch; 36d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kimimport android.media.AudioPort; 37d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kimimport android.media.AudioPortConfig; 38d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputHardware; 39d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.ITvInputHardwareCallback; 40546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seoimport android.media.tv.TvInputHardwareInfo; 41969167dc05a6485a32d160895871cff46fd81884Wonsik Kimimport android.media.tv.TvInputInfo; 42d5cc4a281e7ce29d1e8687ff3394b57a3a549260Jae Seoimport android.media.tv.TvStreamConfig; 43969167dc05a6485a32d160895871cff46fd81884Wonsik Kimimport android.os.Handler; 44c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kimimport android.os.IBinder; 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 55e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kimimport com.android.internal.os.SomeArgs; 56969167dc05a6485a32d160895871cff46fd81884Wonsik Kimimport com.android.server.SystemService; 57969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 58c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kimimport java.util.ArrayList; 598e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kimimport java.util.Arrays; 604f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Leeimport java.util.Collections; 61d922a546b94119217fb790113d0001cad0432060Wonsik Kimimport java.util.Iterator; 62d922a546b94119217fb790113d0001cad0432060Wonsik Kimimport java.util.LinkedList; 63c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kimimport java.util.List; 644f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Leeimport java.util.Map; 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 Listener mListener; 78c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private final TvInputHal mHal = new TvInputHal(this); 79d922a546b94119217fb790113d0001cad0432060Wonsik Kim private final SparseArray<Connection> mConnections = new SparseArray<>(); 80d922a546b94119217fb790113d0001cad0432060Wonsik Kim private final List<TvInputHardwareInfo> mHardwareList = new ArrayList<>(); 81546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo private final List<HdmiDeviceInfo> mHdmiDeviceList = new LinkedList<>(); 824f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee /* A map from a device ID to the matching TV input ID. */ 83d922a546b94119217fb790113d0001cad0432060Wonsik Kim private final SparseArray<String> mHardwareInputIdMap = new SparseArray<>(); 844f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee /* A map from a HDMI logical address to the matching TV input ID. */ 85546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo private final SparseArray<String> mHdmiInputIdMap = new SparseArray<>(); 86d922a546b94119217fb790113d0001cad0432060Wonsik Kim private final Map<String, TvInputInfo> mInputMap = new ArrayMap<>(); 874f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 88d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim private final AudioManager mAudioManager; 894f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private IHdmiControlService mHdmiControlService; 907474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim private final IHdmiHotplugEventListener mHdmiHotplugEventListener = 917474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim new HdmiHotplugEventListener(); 924f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private final IHdmiDeviceEventListener mHdmiDeviceEventListener = new HdmiDeviceEventListener(); 931f819bbfc80f0ae9de120e9b81250db36629a0b1Jungshik Jang private final IHdmiSystemAudioModeChangeListener mHdmiSystemAudioModeChangeListener = 941f819bbfc80f0ae9de120e9b81250db36629a0b1Jungshik Jang new HdmiSystemAudioModeChangeListener(); 95d38bf476f6a31602e92a3207a4ceb29bf965f9aaJinsuk Kim 96d922a546b94119217fb790113d0001cad0432060Wonsik Kim // TODO: Should handle STANDBY case. 974f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee private final SparseBooleanArray mHdmiStateMap = new SparseBooleanArray(); 98d922a546b94119217fb790113d0001cad0432060Wonsik Kim private final List<Message> mPendingHdmiDeviceEvents = new LinkedList<>(); 99969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 100187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim // Calls to mListener should happen here. 101187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final Handler mHandler = new ListenerHandler(); 102c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 103c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private final Object mLock = new Object(); 104c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 105187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public TvInputHardwareManager(Context context, Listener listener) { 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); 1191f819bbfc80f0ae9de120e9b81250db36629a0b1Jungshik Jang mHdmiControlService.addSystemAudioModeChangeListener( 1201f819bbfc80f0ae9de120e9b81250db36629a0b1Jungshik Jang mHdmiSystemAudioModeChangeListener); 121546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo mHdmiDeviceList.addAll(mHdmiControlService.getInputDevices()); 1227474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim } catch (RemoteException e) { 1234f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee Slog.w(TAG, "Error registering listeners to HdmiControlService:", e); 1247474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim } 12508f1ab02d6de42756825a2dfa7027137ff959bd8Jinsuk Kim } else { 12608f1ab02d6de42756825a2dfa7027137ff959bd8Jinsuk Kim Slog.w(TAG, "HdmiControlService is not available"); 1277474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim } 128969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 129c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 130c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 131c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 1324f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void onDeviceAvailable(TvInputHardwareInfo info, TvStreamConfig[] configs) { 133c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim synchronized (mLock) { 134c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Connection connection = new Connection(info); 135c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim connection.updateConfigsLocked(configs); 136c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mConnections.put(info.getDeviceId(), connection); 137d922a546b94119217fb790113d0001cad0432060Wonsik Kim buildHardwareListLocked(); 138187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mHandler.obtainMessage( 139187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim ListenerHandler.HARDWARE_DEVICE_ADDED, 0, 0, info).sendToTarget(); 140d922a546b94119217fb790113d0001cad0432060Wonsik Kim if (info.getType() == TvInputHardwareInfo.TV_INPUT_TYPE_HDMI) { 141d922a546b94119217fb790113d0001cad0432060Wonsik Kim processPendingHdmiDeviceEventsLocked(); 142d922a546b94119217fb790113d0001cad0432060Wonsik Kim } 143c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 144c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 145c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 146d922a546b94119217fb790113d0001cad0432060Wonsik Kim private void buildHardwareListLocked() { 147d922a546b94119217fb790113d0001cad0432060Wonsik Kim mHardwareList.clear(); 148c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim for (int i = 0; i < mConnections.size(); ++i) { 149d922a546b94119217fb790113d0001cad0432060Wonsik Kim mHardwareList.add(mConnections.valueAt(i).getHardwareInfoLocked()); 150c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 151c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 152c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 153c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 154c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public void onDeviceUnavailable(int deviceId) { 155c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim synchronized (mLock) { 156c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Connection connection = mConnections.get(deviceId); 157c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim if (connection == null) { 158c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Slog.e(TAG, "onDeviceUnavailable: Cannot find a connection with " + deviceId); 159c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return; 160c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 161969167dc05a6485a32d160895871cff46fd81884Wonsik Kim connection.resetLocked(null, null, null, null, null); 162c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mConnections.remove(deviceId); 163d922a546b94119217fb790113d0001cad0432060Wonsik Kim buildHardwareListLocked(); 1644f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee TvInputHardwareInfo info = connection.getHardwareInfoLocked(); 165d922a546b94119217fb790113d0001cad0432060Wonsik Kim if (info.getType() == TvInputHardwareInfo.TV_INPUT_TYPE_HDMI) { 166546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo // Remove HDMI devices linked with this hardware. 167546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo for (Iterator<HdmiDeviceInfo> it = mHdmiDeviceList.iterator(); it.hasNext();) { 16861f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang HdmiDeviceInfo deviceInfo = it.next(); 169d922a546b94119217fb790113d0001cad0432060Wonsik Kim if (deviceInfo.getPortId() == info.getHdmiPortId()) { 170546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo mHandler.obtainMessage(ListenerHandler.HDMI_DEVICE_REMOVED, 0, 0, 171d922a546b94119217fb790113d0001cad0432060Wonsik Kim deviceInfo).sendToTarget(); 172d922a546b94119217fb790113d0001cad0432060Wonsik Kim it.remove(); 173d922a546b94119217fb790113d0001cad0432060Wonsik Kim } 174d922a546b94119217fb790113d0001cad0432060Wonsik Kim } 175d922a546b94119217fb790113d0001cad0432060Wonsik Kim } 176187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mHandler.obtainMessage( 1774f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee ListenerHandler.HARDWARE_DEVICE_REMOVED, 0, 0, info).sendToTarget(); 178c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 179c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 180c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 181c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 182c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public void onStreamConfigurationChanged(int deviceId, TvStreamConfig[] configs) { 183c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim synchronized (mLock) { 184c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Connection connection = mConnections.get(deviceId); 185c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim if (connection == null) { 186c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Slog.e(TAG, "StreamConfigurationChanged: Cannot find a connection with " 187c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim + deviceId); 188c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return; 189c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 190c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim connection.updateConfigsLocked(configs); 1919a1036575182705bc27c6bf255dd17669821181dWonsik Kim String inputId = mHardwareInputIdMap.get(deviceId); 1929a1036575182705bc27c6bf255dd17669821181dWonsik Kim if (inputId != null) { 1939a1036575182705bc27c6bf255dd17669821181dWonsik Kim mHandler.obtainMessage(ListenerHandler.STATE_CHANGED, 1945b820a8aa1a200824e44aede6bc1e381a6d69dd5Wonsik Kim convertConnectedToState(configs.length > 0), 0, inputId).sendToTarget(); 1959a1036575182705bc27c6bf255dd17669821181dWonsik Kim } 196c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 197c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim connection.getCallbackLocked().onStreamConfigChanged(configs); 198c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } catch (RemoteException e) { 1994f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee Slog.e(TAG, "error in onStreamConfigurationChanged", e); 200c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 201c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 202c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 203c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 204c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo @Override 205c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo public void onFirstFrameCaptured(int deviceId, int streamId) { 206c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo synchronized (mLock) { 207c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Connection connection = mConnections.get(deviceId); 208c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (connection == null) { 209c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Slog.e(TAG, "FirstFrameCaptured: Cannot find a connection with " 210c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo + deviceId); 211c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return; 212c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 213c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Runnable runnable = connection.getOnFirstFrameCapturedLocked(); 214c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (runnable != null) { 215c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo runnable.run(); 216c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo connection.setOnFirstFrameCapturedLocked(null); 217c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 218c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 219c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 220c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 221c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public List<TvInputHardwareInfo> getHardwareList() { 222c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim synchronized (mLock) { 223d922a546b94119217fb790113d0001cad0432060Wonsik Kim return Collections.unmodifiableList(mHardwareList); 224c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 225c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 226c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 227546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo public List<HdmiDeviceInfo> getHdmiDeviceList() { 228d922a546b94119217fb790113d0001cad0432060Wonsik Kim synchronized (mLock) { 229546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo return Collections.unmodifiableList(mHdmiDeviceList); 2304f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 2314f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 2324f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 233e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim private boolean checkUidChangedLocked( 234e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim Connection connection, int callingUid, int resolvedUserId) { 235e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim Integer connectionCallingUid = connection.getCallingUidLocked(); 236e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim Integer connectionResolvedUserId = connection.getResolvedUserIdLocked(); 237e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim if (connectionCallingUid == null || connectionResolvedUserId == null) { 238e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim return true; 239e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim } 240e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim if (connectionCallingUid != callingUid || connectionResolvedUserId != resolvedUserId) { 241e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim return true; 242e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim } 243e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim return false; 244e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim } 245e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim 246969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private int convertConnectedToState(boolean connected) { 247969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (connected) { 248969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return INPUT_STATE_CONNECTED; 249969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } else { 250969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return INPUT_STATE_DISCONNECTED; 251969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 252969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 253969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 2544f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void addHardwareTvInput(int deviceId, TvInputInfo info) { 255969167dc05a6485a32d160895871cff46fd81884Wonsik Kim synchronized (mLock) { 2564f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee String oldInputId = mHardwareInputIdMap.get(deviceId); 2574f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (oldInputId != null) { 258969167dc05a6485a32d160895871cff46fd81884Wonsik Kim Slog.w(TAG, "Trying to override previous registration: old = " 2594f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee + mInputMap.get(oldInputId) + ":" + deviceId + ", new = " 260969167dc05a6485a32d160895871cff46fd81884Wonsik Kim + info + ":" + deviceId); 261969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 2624f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mHardwareInputIdMap.put(deviceId, info.getId()); 2634f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mInputMap.put(info.getId(), info); 264969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 2659a1036575182705bc27c6bf255dd17669821181dWonsik Kim // Process pending state changes 2669a1036575182705bc27c6bf255dd17669821181dWonsik Kim 2679a1036575182705bc27c6bf255dd17669821181dWonsik Kim // For logical HDMI devices, they have information from HDMI CEC signals. 268969167dc05a6485a32d160895871cff46fd81884Wonsik Kim for (int i = 0; i < mHdmiStateMap.size(); ++i) { 269d922a546b94119217fb790113d0001cad0432060Wonsik Kim TvInputHardwareInfo hardwareInfo = 270d922a546b94119217fb790113d0001cad0432060Wonsik Kim findHardwareInfoForHdmiPortLocked(mHdmiStateMap.keyAt(i)); 271d922a546b94119217fb790113d0001cad0432060Wonsik Kim if (hardwareInfo == null) { 272d922a546b94119217fb790113d0001cad0432060Wonsik Kim continue; 273d922a546b94119217fb790113d0001cad0432060Wonsik Kim } 274d922a546b94119217fb790113d0001cad0432060Wonsik Kim String inputId = mHardwareInputIdMap.get(hardwareInfo.getDeviceId()); 275969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (inputId != null && inputId.equals(info.getId())) { 276187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mHandler.obtainMessage(ListenerHandler.STATE_CHANGED, 277969167dc05a6485a32d160895871cff46fd81884Wonsik Kim convertConnectedToState(mHdmiStateMap.valueAt(i)), 0, 278969167dc05a6485a32d160895871cff46fd81884Wonsik Kim inputId).sendToTarget(); 2799a1036575182705bc27c6bf255dd17669821181dWonsik Kim return; 280969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 281969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 2829a1036575182705bc27c6bf255dd17669821181dWonsik Kim // For the rest of the devices, we can tell by the number of available streams. 2839a1036575182705bc27c6bf255dd17669821181dWonsik Kim Connection connection = mConnections.get(deviceId); 2849a1036575182705bc27c6bf255dd17669821181dWonsik Kim if (connection != null) { 2859a1036575182705bc27c6bf255dd17669821181dWonsik Kim mHandler.obtainMessage(ListenerHandler.STATE_CHANGED, 2869a1036575182705bc27c6bf255dd17669821181dWonsik Kim convertConnectedToState(connection.getConfigsLocked().length > 0), 0, 2879a1036575182705bc27c6bf255dd17669821181dWonsik Kim info.getId()).sendToTarget(); 2889a1036575182705bc27c6bf255dd17669821181dWonsik Kim return; 2899a1036575182705bc27c6bf255dd17669821181dWonsik Kim } 290969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 291969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 292969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 29338feae971c43700c9cb15aafbf8bd37340675a50Wonsik Kim private static <T> int indexOfEqualValue(SparseArray<T> map, T value) { 29438feae971c43700c9cb15aafbf8bd37340675a50Wonsik Kim for (int i = 0; i < map.size(); ++i) { 29538feae971c43700c9cb15aafbf8bd37340675a50Wonsik Kim if (map.valueAt(i).equals(value)) { 29638feae971c43700c9cb15aafbf8bd37340675a50Wonsik Kim return i; 29738feae971c43700c9cb15aafbf8bd37340675a50Wonsik Kim } 29838feae971c43700c9cb15aafbf8bd37340675a50Wonsik Kim } 29938feae971c43700c9cb15aafbf8bd37340675a50Wonsik Kim return -1; 30038feae971c43700c9cb15aafbf8bd37340675a50Wonsik Kim } 30138feae971c43700c9cb15aafbf8bd37340675a50Wonsik Kim 3028960d1b1552729e3dfd33deee951ac75933ad8e5Jinsuk Kim public void addHdmiTvInput(int id, TvInputInfo info) { 3034f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (info.getType() != TvInputInfo.TYPE_HDMI) { 3044f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee throw new IllegalArgumentException("info (" + info + ") has non-HDMI type."); 3054f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 3064f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee synchronized (mLock) { 3074f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee String parentId = info.getParentId(); 30838feae971c43700c9cb15aafbf8bd37340675a50Wonsik Kim int parentIndex = indexOfEqualValue(mHardwareInputIdMap, parentId); 30938feae971c43700c9cb15aafbf8bd37340675a50Wonsik Kim if (parentIndex < 0) { 3104f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee throw new IllegalArgumentException("info (" + info + ") has invalid parentId."); 3114f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 3128960d1b1552729e3dfd33deee951ac75933ad8e5Jinsuk Kim String oldInputId = mHdmiInputIdMap.get(id); 3134f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (oldInputId != null) { 3144f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee Slog.w(TAG, "Trying to override previous registration: old = " 3158960d1b1552729e3dfd33deee951ac75933ad8e5Jinsuk Kim + mInputMap.get(oldInputId) + ":" + id + ", new = " 3168960d1b1552729e3dfd33deee951ac75933ad8e5Jinsuk Kim + info + ":" + id); 3174f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 3188960d1b1552729e3dfd33deee951ac75933ad8e5Jinsuk Kim mHdmiInputIdMap.put(id, info.getId()); 3194f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mInputMap.put(info.getId(), info); 3204f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 3214f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 3224f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 3234f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void removeTvInput(String inputId) { 3244f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee synchronized (mLock) { 3254f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mInputMap.remove(inputId); 32638feae971c43700c9cb15aafbf8bd37340675a50Wonsik Kim int hardwareIndex = indexOfEqualValue(mHardwareInputIdMap, inputId); 3274f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee if (hardwareIndex >= 0) { 3284f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mHardwareInputIdMap.removeAt(hardwareIndex); 3294f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 330546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo int deviceIndex = indexOfEqualValue(mHdmiInputIdMap, inputId); 331546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo if (deviceIndex >= 0) { 332546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo mHdmiInputIdMap.removeAt(deviceIndex); 3334f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 3344f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 3354f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee } 3364f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee 337c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim /** 338c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * Create a TvInputHardware object with a specific deviceId. One service at a time can access 339c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * the object, and if more than one process attempts to create hardware with the same deviceId, 340c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * the latest service will get the object and all the other hardware are released. The 341c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * release is notified via ITvInputHardwareCallback.onReleased(). 342c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim */ 343c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public ITvInputHardware acquireHardware(int deviceId, ITvInputHardwareCallback callback, 344969167dc05a6485a32d160895871cff46fd81884Wonsik Kim TvInputInfo info, int callingUid, int resolvedUserId) { 345c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim if (callback == null) { 346c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim throw new NullPointerException(); 347c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 348c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim synchronized (mLock) { 349c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Connection connection = mConnections.get(deviceId); 350c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim if (connection == null) { 351c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Slog.e(TAG, "Invalid deviceId : " + deviceId); 352c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return null; 353c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 354e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim if (checkUidChangedLocked(connection, callingUid, resolvedUserId)) { 355969167dc05a6485a32d160895871cff46fd81884Wonsik Kim TvInputHardwareImpl hardware = 356969167dc05a6485a32d160895871cff46fd81884Wonsik Kim new TvInputHardwareImpl(connection.getHardwareInfoLocked()); 357c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 358c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim callback.asBinder().linkToDeath(connection, 0); 359c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } catch (RemoteException e) { 360c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim hardware.release(); 361c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return null; 362c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 363969167dc05a6485a32d160895871cff46fd81884Wonsik Kim connection.resetLocked(hardware, callback, info, callingUid, resolvedUserId); 364c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 365c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return connection.getHardwareLocked(); 366c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 367c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 368c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 369c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim /** 370c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim * Release the specified hardware. 371c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim */ 372c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public void releaseHardware(int deviceId, ITvInputHardware hardware, int callingUid, 373c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim int resolvedUserId) { 374c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim synchronized (mLock) { 375c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Connection connection = mConnections.get(deviceId); 376c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim if (connection == null) { 377c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim Slog.e(TAG, "Invalid deviceId : " + deviceId); 378c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return; 379c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 380c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim if (connection.getHardwareLocked() != hardware 381e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim || checkUidChangedLocked(connection, callingUid, resolvedUserId)) { 382c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return; 383c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 384969167dc05a6485a32d160895871cff46fd81884Wonsik Kim connection.resetLocked(null, null, null, null, null); 385969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 386969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 387969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 388d922a546b94119217fb790113d0001cad0432060Wonsik Kim private TvInputHardwareInfo findHardwareInfoForHdmiPortLocked(int port) { 389d922a546b94119217fb790113d0001cad0432060Wonsik Kim for (TvInputHardwareInfo hardwareInfo : mHardwareList) { 390969167dc05a6485a32d160895871cff46fd81884Wonsik Kim if (hardwareInfo.getType() == TvInputHardwareInfo.TV_INPUT_TYPE_HDMI 391969167dc05a6485a32d160895871cff46fd81884Wonsik Kim && hardwareInfo.getHdmiPortId() == port) { 392d922a546b94119217fb790113d0001cad0432060Wonsik Kim return hardwareInfo; 393969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 394969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 395969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return null; 396969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 397969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 398c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo private int findDeviceIdForInputIdLocked(String inputId) { 399c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo for (int i = 0; i < mConnections.size(); ++i) { 400c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Connection connection = mConnections.get(i); 401c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (connection.getInfoLocked().getId().equals(inputId)) { 402c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return i; 403c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 404c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 405c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return -1; 406c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 407c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 408c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo /** 409c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo * Get the list of TvStreamConfig which is buffered mode. 410c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo */ 411c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo public List<TvStreamConfig> getAvailableTvStreamConfigList(String inputId, int callingUid, 412c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo int resolvedUserId) { 413c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo List<TvStreamConfig> configsList = new ArrayList<TvStreamConfig>(); 414c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo synchronized (mLock) { 415c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo int deviceId = findDeviceIdForInputIdLocked(inputId); 416c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (deviceId < 0) { 417c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Slog.e(TAG, "Invalid inputId : " + inputId); 418c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return configsList; 419c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 420c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Connection connection = mConnections.get(deviceId); 421c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo for (TvStreamConfig config : connection.getConfigsLocked()) { 422c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (config.getType() == TvStreamConfig.STREAM_TYPE_BUFFER_PRODUCER) { 423c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo configsList.add(config); 424c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 425c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 426c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 427c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return configsList; 428c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 429c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 430c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo /** 431c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo * Take a snapshot of the given TV input into the provided Surface. 432c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo */ 433c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo public boolean captureFrame(String inputId, Surface surface, final TvStreamConfig config, 434c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo int callingUid, int resolvedUserId) { 435c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo synchronized (mLock) { 436c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo int deviceId = findDeviceIdForInputIdLocked(inputId); 437c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (deviceId < 0) { 438c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Slog.e(TAG, "Invalid inputId : " + inputId); 439c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return false; 440c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 441c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Connection connection = mConnections.get(deviceId); 442c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo final TvInputHardwareImpl hardwareImpl = connection.getHardwareImplLocked(); 443c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (hardwareImpl != null) { 444c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo // Stop previous capture. 445c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo Runnable runnable = connection.getOnFirstFrameCapturedLocked(); 446c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (runnable != null) { 447c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo runnable.run(); 448c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo connection.setOnFirstFrameCapturedLocked(null); 449c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 450c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 451c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo boolean result = hardwareImpl.startCapture(surface, config); 452c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (result) { 453c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo connection.setOnFirstFrameCapturedLocked(new Runnable() { 454c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo @Override 455c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo public void run() { 456c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo hardwareImpl.stopCapture(config); 457c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 458c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo }); 459c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 460c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return result; 461c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 462c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 463c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return false; 464c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 465c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 466d922a546b94119217fb790113d0001cad0432060Wonsik Kim private void processPendingHdmiDeviceEventsLocked() { 467d922a546b94119217fb790113d0001cad0432060Wonsik Kim for (Iterator<Message> it = mPendingHdmiDeviceEvents.iterator(); it.hasNext(); ) { 468d922a546b94119217fb790113d0001cad0432060Wonsik Kim Message msg = it.next(); 46961f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang HdmiDeviceInfo deviceInfo = (HdmiDeviceInfo) msg.obj; 470d922a546b94119217fb790113d0001cad0432060Wonsik Kim TvInputHardwareInfo hardwareInfo = 471d922a546b94119217fb790113d0001cad0432060Wonsik Kim findHardwareInfoForHdmiPortLocked(deviceInfo.getPortId()); 472d922a546b94119217fb790113d0001cad0432060Wonsik Kim if (hardwareInfo != null) { 473d922a546b94119217fb790113d0001cad0432060Wonsik Kim msg.sendToTarget(); 474d922a546b94119217fb790113d0001cad0432060Wonsik Kim it.remove(); 475d922a546b94119217fb790113d0001cad0432060Wonsik Kim } 476d922a546b94119217fb790113d0001cad0432060Wonsik Kim } 477d922a546b94119217fb790113d0001cad0432060Wonsik Kim } 478d922a546b94119217fb790113d0001cad0432060Wonsik Kim 479c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private class Connection implements IBinder.DeathRecipient { 480969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private final TvInputHardwareInfo mHardwareInfo; 481969167dc05a6485a32d160895871cff46fd81884Wonsik Kim private TvInputInfo mInfo; 482c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private TvInputHardwareImpl mHardware = null; 483c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private ITvInputHardwareCallback mCallback; 484c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private TvStreamConfig[] mConfigs = null; 485c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private Integer mCallingUid = null; 486c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private Integer mResolvedUserId = null; 487c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo private Runnable mOnFirstFrameCaptured; 488c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 489969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public Connection(TvInputHardwareInfo hardwareInfo) { 490969167dc05a6485a32d160895871cff46fd81884Wonsik Kim mHardwareInfo = hardwareInfo; 491c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 492c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 493c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim // *Locked methods assume TvInputHardwareManager.mLock is held. 494c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 495969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public void resetLocked(TvInputHardwareImpl hardware, ITvInputHardwareCallback callback, 496969167dc05a6485a32d160895871cff46fd81884Wonsik Kim TvInputInfo info, Integer callingUid, Integer resolvedUserId) { 497c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim if (mHardware != null) { 498c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 499c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mCallback.onReleased(); 500c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } catch (RemoteException e) { 5014f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee Slog.e(TAG, "error in Connection::resetLocked", e); 502c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 503c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mHardware.release(); 504c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 505c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mHardware = hardware; 506c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mCallback = callback; 507969167dc05a6485a32d160895871cff46fd81884Wonsik Kim mInfo = info; 508c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mCallingUid = callingUid; 509c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mResolvedUserId = resolvedUserId; 510c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo mOnFirstFrameCaptured = null; 511c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 512c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim if (mHardware != null && mCallback != null) { 513c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim try { 514c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mCallback.onStreamConfigChanged(getConfigsLocked()); 515c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } catch (RemoteException e) { 5164f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee Slog.e(TAG, "error in Connection::resetLocked", e); 517c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 518c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 519c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 520c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 521c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public void updateConfigsLocked(TvStreamConfig[] configs) { 522c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mConfigs = configs; 523c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 524c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 525969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public TvInputHardwareInfo getHardwareInfoLocked() { 526969167dc05a6485a32d160895871cff46fd81884Wonsik Kim return mHardwareInfo; 527969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 528969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 529969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public TvInputInfo getInfoLocked() { 530c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return mInfo; 531c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 532c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 533c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public ITvInputHardware getHardwareLocked() { 534c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return mHardware; 535c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 536c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 537c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo public TvInputHardwareImpl getHardwareImplLocked() { 538c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return mHardware; 539c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 540c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 541c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public ITvInputHardwareCallback getCallbackLocked() { 542c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return mCallback; 543c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 544c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 545c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public TvStreamConfig[] getConfigsLocked() { 546c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return mConfigs; 547c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 548c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 549e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim public Integer getCallingUidLocked() { 550c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return mCallingUid; 551c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 552c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 553e7ae0ce53b6e1ddee3e456d2a69eebcd5a196b1fWonsik Kim public Integer getResolvedUserIdLocked() { 554c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return mResolvedUserId; 555c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 556c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 557c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo public void setOnFirstFrameCapturedLocked(Runnable runnable) { 558c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo mOnFirstFrameCaptured = runnable; 559c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 560c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 561c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo public Runnable getOnFirstFrameCapturedLocked() { 562c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return mOnFirstFrameCaptured; 563c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 564c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 565c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 566c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public void binderDied() { 567c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim synchronized (mLock) { 568969167dc05a6485a32d160895871cff46fd81884Wonsik Kim resetLocked(null, null, null, null, null); 569c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 570c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 571c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 572c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 573c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private class TvInputHardwareImpl extends ITvInputHardware.Stub { 574c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private final TvInputHardwareInfo mInfo; 575c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private boolean mReleased = false; 576c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim private final Object mImplLock = new Object(); 577c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 57806c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim private final AudioManager.OnAudioPortUpdateListener mAudioListener = 57906c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim new AudioManager.OnAudioPortUpdateListener() { 58006c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim @Override 58106c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim public void onAudioPortListUpdate(AudioPort[] portList) { 58206c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim synchronized (mImplLock) { 5837587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim updateAudioConfigLocked(); 58406c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim } 58506c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim } 58606c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim 58706c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim @Override 58806c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim public void onAudioPatchListUpdate(AudioPatch[] patchList) { 58906c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim // No-op 59006c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim } 59106c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim 59206c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim @Override 59306c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim public void onServiceDied() { 59406c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim synchronized (mImplLock) { 59506c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim mAudioSource = null; 59606c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim mAudioSink = null; 59706c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim mAudioPatch = null; 59806c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim } 59906c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim } 60006c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim }; 60106c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim private int mOverrideAudioType = AudioManager.DEVICE_NONE; 60206c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim private String mOverrideAudioAddress = ""; 60306c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim private AudioDevicePort mAudioSource; 604ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim private AudioDevicePort mAudioSink; 605d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim private AudioPatch mAudioPatch = null; 6068e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim private float mCommittedVolume = 0.0f; 6078e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim private float mVolume = 0.0f; 608d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim 609839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim private TvStreamConfig mActiveConfig = null; 610839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim 611ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim private int mDesiredSamplingRate = 0; 612ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim private int mDesiredChannelMask = AudioFormat.CHANNEL_OUT_DEFAULT; 613ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim private int mDesiredFormat = AudioFormat.ENCODING_DEFAULT; 614ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim 615c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public TvInputHardwareImpl(TvInputHardwareInfo info) { 616c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mInfo = info; 61706c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim mAudioManager.registerAudioPortUpdateListener(mAudioListener); 618d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim if (mInfo.getAudioType() != AudioManager.DEVICE_NONE) { 61906c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim mAudioSource = findAudioDevicePort(mInfo.getAudioType(), mInfo.getAudioAddress()); 620ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim mAudioSink = findAudioSinkFromAudioPolicy(); 621ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim } 622ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim } 623ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim 624ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim private AudioDevicePort findAudioSinkFromAudioPolicy() { 625ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim ArrayList<AudioPort> devicePorts = new ArrayList<AudioPort>(); 626ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim if (mAudioManager.listAudioDevicePorts(devicePorts) == AudioManager.SUCCESS) { 627ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim int sinkDevice = mAudioManager.getDevicesForStream(AudioManager.STREAM_MUSIC); 628ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim for (AudioPort port : devicePorts) { 629ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim AudioDevicePort devicePort = (AudioDevicePort) port; 6301f819bbfc80f0ae9de120e9b81250db36629a0b1Jungshik Jang if ((devicePort.type() & sinkDevice) != 0) { 631ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim return devicePort; 632d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim } 633d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim } 634d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim } 635ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim return null; 636ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim } 637ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim 638ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim private AudioDevicePort findAudioDevicePort(int type, String address) { 639ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim if (type == AudioManager.DEVICE_NONE) { 640ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim return null; 641ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim } 642ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim ArrayList<AudioPort> devicePorts = new ArrayList<AudioPort>(); 643ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim if (mAudioManager.listAudioDevicePorts(devicePorts) != AudioManager.SUCCESS) { 644ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim return null; 645ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim } 646ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim for (AudioPort port : devicePorts) { 647ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim AudioDevicePort devicePort = (AudioDevicePort) port; 648ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim if (devicePort.type() == type && devicePort.address().equals(address)) { 649ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim return devicePort; 650ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim } 651ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim } 652ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim return null; 653c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 654c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 655c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public void release() { 656c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim synchronized (mImplLock) { 65706c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim mAudioManager.unregisterAudioPortUpdateListener(mAudioListener); 658d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim if (mAudioPatch != null) { 659d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim mAudioManager.releaseAudioPatch(mAudioPatch); 660d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim mAudioPatch = null; 661d7c29189aa639bfac1e6efcd222e65c2c8ecf3f1Wonsik Kim } 662c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim mReleased = true; 663c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 664c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 665c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 666839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim // A TvInputHardwareImpl object holds only one active session. Therefore, if a client 667839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim // attempts to call setSurface with different TvStreamConfig objects, the last call will 668839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim // prevail. 669c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 670c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public boolean setSurface(Surface surface, TvStreamConfig config) 671c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim throws RemoteException { 672c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim synchronized (mImplLock) { 673c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim if (mReleased) { 674c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim throw new IllegalStateException("Device already released."); 675c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 6767587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim 677102670f16a44d4b25d7e3a252bedee0208b68c55Wonsik Kim int result = TvInputHal.SUCCESS; 678839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim if (surface == null) { 679b683e6e4c70da3644427cb5ec6a8342b3a91bb23Wonsik Kim // The value of config is ignored when surface == null. 680b683e6e4c70da3644427cb5ec6a8342b3a91bb23Wonsik Kim if (mActiveConfig != null) { 681b683e6e4c70da3644427cb5ec6a8342b3a91bb23Wonsik Kim result = mHal.removeStream(mInfo.getDeviceId(), mActiveConfig); 682b683e6e4c70da3644427cb5ec6a8342b3a91bb23Wonsik Kim mActiveConfig = null; 683b683e6e4c70da3644427cb5ec6a8342b3a91bb23Wonsik Kim } else { 684b683e6e4c70da3644427cb5ec6a8342b3a91bb23Wonsik Kim // We already have no active stream. 685b683e6e4c70da3644427cb5ec6a8342b3a91bb23Wonsik Kim return true; 686b683e6e4c70da3644427cb5ec6a8342b3a91bb23Wonsik Kim } 687839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim } else { 688b683e6e4c70da3644427cb5ec6a8342b3a91bb23Wonsik Kim // It's impossible to set a non-null surface with a null config. 689b683e6e4c70da3644427cb5ec6a8342b3a91bb23Wonsik Kim if (config == null) { 690b683e6e4c70da3644427cb5ec6a8342b3a91bb23Wonsik Kim return false; 691b683e6e4c70da3644427cb5ec6a8342b3a91bb23Wonsik Kim } 692b683e6e4c70da3644427cb5ec6a8342b3a91bb23Wonsik Kim // Remove stream only if we have an existing active configuration. 693b683e6e4c70da3644427cb5ec6a8342b3a91bb23Wonsik Kim if (mActiveConfig != null && !config.equals(mActiveConfig)) { 694839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim result = mHal.removeStream(mInfo.getDeviceId(), mActiveConfig); 695839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim if (result != TvInputHal.SUCCESS) { 696839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim mActiveConfig = null; 697839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim } 698839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim } 699b683e6e4c70da3644427cb5ec6a8342b3a91bb23Wonsik Kim // Proceed only if all previous operations succeeded. 700839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim if (result == TvInputHal.SUCCESS) { 701b683e6e4c70da3644427cb5ec6a8342b3a91bb23Wonsik Kim result = mHal.addOrUpdateStream(mInfo.getDeviceId(), surface, config); 702b683e6e4c70da3644427cb5ec6a8342b3a91bb23Wonsik Kim if (result == TvInputHal.SUCCESS) { 703b683e6e4c70da3644427cb5ec6a8342b3a91bb23Wonsik Kim mActiveConfig = config; 704b683e6e4c70da3644427cb5ec6a8342b3a91bb23Wonsik Kim } 705839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim } 706839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim } 7077587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim updateAudioConfigLocked(); 708839ae5f460caadf8580b7e0ab77e255d7a1ddae5Wonsik Kim return result == TvInputHal.SUCCESS; 709c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 710c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 711c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 7127587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim /** 7137587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim * Update audio configuration (source, sink, patch) all up to current state. 7147587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim */ 7157587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim private void updateAudioConfigLocked() { 7167587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim boolean sinkUpdated = updateAudioSinkLocked(); 7177587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim boolean sourceUpdated = updateAudioSourceLocked(); 7187587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim // We can't do updated = updateAudioSinkLocked() || updateAudioSourceLocked() here 7197587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim // because Java won't evaluate the latter if the former is true. 7207587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim 7217587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim if (mAudioSource == null || mAudioSink == null || mActiveConfig == null) { 72206c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim if (mAudioPatch != null) { 7237587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim mAudioManager.releaseAudioPatch(mAudioPatch); 7247587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim mAudioPatch = null; 72506c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim } 72606c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim return; 72706c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim } 72806c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim 7298e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim AudioGainConfig sourceGainConfig = null; 7308e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim if (mAudioSource.gains().length > 0 && mVolume != mCommittedVolume) { 7318e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim AudioGain sourceGain = null; 7328e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim for (AudioGain gain : mAudioSource.gains()) { 7338e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim if ((gain.mode() & AudioGain.MODE_JOINT) != 0) { 7348e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim sourceGain = gain; 7358e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim break; 7368e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim } 7378e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim } 7388e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim // NOTE: we only change the source gain in MODE_JOINT here. 7398e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim if (sourceGain != null) { 7408e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim int steps = (sourceGain.maxValue() - sourceGain.minValue()) 7418e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim / sourceGain.stepValue(); 7428e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim int gainValue = sourceGain.minValue(); 7438e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim if (mVolume < 1.0f) { 7448e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim gainValue += sourceGain.stepValue() * (int) (mVolume * steps + 0.5); 7458e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim } else { 7468e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim gainValue = sourceGain.maxValue(); 7478e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim } 7488e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim int numChannels = 0; 7498e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim for (int mask = sourceGain.channelMask(); mask > 0; mask >>= 1) { 7508e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim numChannels += (mask & 1); 7518e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim } 7528e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim int[] gainValues = new int[numChannels]; 7538e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim Arrays.fill(gainValues, gainValue); 7548e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim sourceGainConfig = sourceGain.buildConfig(AudioGain.MODE_JOINT, 7558e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim sourceGain.channelMask(), gainValues, 0); 7568e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim } else { 7578e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim Slog.w(TAG, "No audio source gain with MODE_JOINT support exists."); 7588e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim } 7598e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim } 7608e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim 761ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim AudioPortConfig sourceConfig = mAudioSource.activeConfig(); 762ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim AudioPortConfig sinkConfig = mAudioSink.activeConfig(); 763ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim AudioPatch[] audioPatchArray = new AudioPatch[] { mAudioPatch }; 7647587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim boolean shouldRecreateAudioPatch = sourceUpdated || sinkUpdated; 765ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim if (sinkConfig == null 766ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim || (mDesiredSamplingRate != 0 767ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim && sinkConfig.samplingRate() != mDesiredSamplingRate) 768ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim || (mDesiredChannelMask != AudioFormat.CHANNEL_OUT_DEFAULT 769ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim && sinkConfig.channelMask() != mDesiredChannelMask) 770ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim || (mDesiredFormat != AudioFormat.ENCODING_DEFAULT 771ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim && sinkConfig.format() != mDesiredFormat)) { 772aa4b0d82a1fdb92fbf4f8852f326f2687ee55fa7Wonsik Kim sinkConfig = mAudioSink.buildConfig(mDesiredSamplingRate, mDesiredChannelMask, 773ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim mDesiredFormat, null); 7748e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim shouldRecreateAudioPatch = true; 775ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim } 7768e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim if (sourceConfig == null || sourceGainConfig != null) { 777ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim sourceConfig = mAudioSource.buildConfig(sinkConfig.samplingRate(), 7788e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim sinkConfig.channelMask(), sinkConfig.format(), sourceGainConfig); 7798e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim shouldRecreateAudioPatch = true; 7808e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim } 7818e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim if (shouldRecreateAudioPatch) { 7828e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim mCommittedVolume = mVolume; 7838e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim mAudioManager.createAudioPatch( 7848e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim audioPatchArray, 7858e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim new AudioPortConfig[] { sourceConfig }, 7868e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim new AudioPortConfig[] { sinkConfig }); 7878e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim mAudioPatch = audioPatchArray[0]; 788ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim } 789ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim } 790ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim 791c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 7928e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim public void setStreamVolume(float volume) throws RemoteException { 793c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim synchronized (mImplLock) { 794c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim if (mReleased) { 795c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim throw new IllegalStateException("Device already released."); 796c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 7978e45a33ca8cb6b6a0cf75edf52ffdf86ffe3dd31Wonsik Kim mVolume = volume; 7987587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim updateAudioConfigLocked(); 799c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 800c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 801c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim 802c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim @Override 803c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim public boolean dispatchKeyEventToHdmi(KeyEvent event) throws RemoteException { 804c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim synchronized (mImplLock) { 805c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim if (mReleased) { 806c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim throw new IllegalStateException("Device already released."); 807c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 808c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 809610ccd9117fc1611fcc576d1cb1f717f1ef3fcbfWonsik Kim if (mInfo.getType() != TvInputHardwareInfo.TV_INPUT_TYPE_HDMI) { 810c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return false; 811c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 812c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim // TODO(hdmi): mHdmiClient.sendKeyEvent(event); 813c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim return false; 814c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 815c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 816c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo private boolean startCapture(Surface surface, TvStreamConfig config) { 817c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo synchronized (mImplLock) { 818c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (mReleased) { 819c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return false; 820c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 821c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (surface == null || config == null) { 822c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return false; 823c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 824c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (config.getType() != TvStreamConfig.STREAM_TYPE_BUFFER_PRODUCER) { 825c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return false; 826c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 827c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 8288f24a8b60f9afc1aedb89e7ee80ce65515439600Wonsik Kim int result = mHal.addOrUpdateStream(mInfo.getDeviceId(), surface, config); 829c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return result == TvInputHal.SUCCESS; 830c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 831c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 832c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 833c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo private boolean stopCapture(TvStreamConfig config) { 834c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo synchronized (mImplLock) { 835c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (mReleased) { 836c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return false; 837c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 838c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo if (config == null) { 839c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return false; 840c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 841c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo 842c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo int result = mHal.removeStream(mInfo.getDeviceId(), config); 843c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo return result == TvInputHal.SUCCESS; 844c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 845c086a3df3b28996cd10ebe42c5f59035d054aa0dTerry Heo } 846ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim 8477587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim private boolean updateAudioSourceLocked() { 84806c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim if (mInfo.getAudioType() == AudioManager.DEVICE_NONE) { 8497587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim return false; 85006c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim } 8517587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim AudioDevicePort previousSource = mAudioSource; 8527587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim mAudioSource = findAudioDevicePort(mInfo.getAudioType(), mInfo.getAudioAddress()); 8537587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim return mAudioSource == null ? (previousSource != null) 8547587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim : !mAudioSource.equals(previousSource); 8557587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim } 8567587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim 8577587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim private boolean updateAudioSinkLocked() { 8587587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim if (mInfo.getAudioType() == AudioManager.DEVICE_NONE) { 8597587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim return false; 8607587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim } 8617587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim AudioDevicePort previousSink = mAudioSink; 86206c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim if (mOverrideAudioType == AudioManager.DEVICE_NONE) { 86306c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim mAudioSink = findAudioSinkFromAudioPolicy(); 86406c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim } else { 86506c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim AudioDevicePort audioSink = 86606c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim findAudioDevicePort(mOverrideAudioType, mOverrideAudioAddress); 86706c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim if (audioSink != null) { 86806c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim mAudioSink = audioSink; 86906c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim } 87006c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim } 8717587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim return mAudioSink == null ? (previousSink != null) : !mAudioSink.equals(previousSink); 87206c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim } 87306c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim 8741f819bbfc80f0ae9de120e9b81250db36629a0b1Jungshik Jang private void handleAudioSinkUpdated() { 8751f819bbfc80f0ae9de120e9b81250db36629a0b1Jungshik Jang synchronized (mImplLock) { 8767587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim updateAudioConfigLocked(); 8771f819bbfc80f0ae9de120e9b81250db36629a0b1Jungshik Jang } 8781f819bbfc80f0ae9de120e9b81250db36629a0b1Jungshik Jang } 8791f819bbfc80f0ae9de120e9b81250db36629a0b1Jungshik Jang 880ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim @Override 881ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim public void overrideAudioSink(int audioType, String audioAddress, int samplingRate, 882ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim int channelMask, int format) { 883ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim synchronized (mImplLock) { 88406c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim mOverrideAudioType = audioType; 88506c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim mOverrideAudioAddress = audioAddress; 88606c41a3e7ffd26894b6df3a0e4bfcfa47c48c739Wonsik Kim 887ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim mDesiredSamplingRate = samplingRate; 888ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim mDesiredChannelMask = channelMask; 889ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim mDesiredFormat = format; 890ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim 8917587d298c9dccbcf425204a9879b5c9e6d2a1a7eWonsik Kim updateAudioConfigLocked(); 892ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim } 893ca17a9029dd7b1b87c155e68476eae5ee4efbedeWonsik Kim } 894c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim } 895969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 896187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim interface Listener { 897187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void onStateChanged(String inputId, int state); 898187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim public void onHardwareDeviceAdded(TvInputHardwareInfo info); 8994f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee public void onHardwareDeviceRemoved(TvInputHardwareInfo info); 900546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo public void onHdmiDeviceAdded(HdmiDeviceInfo device); 901546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo public void onHdmiDeviceRemoved(HdmiDeviceInfo device); 902e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim public void onHdmiDeviceUpdated(String inputId, HdmiDeviceInfo device); 903187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 904969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 905187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private class ListenerHandler extends Handler { 906187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private static final int STATE_CHANGED = 1; 907187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private static final int HARDWARE_DEVICE_ADDED = 2; 908187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private static final int HARDWARE_DEVICE_REMOVED = 3; 909546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo private static final int HDMI_DEVICE_ADDED = 4; 910546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo private static final int HDMI_DEVICE_REMOVED = 5; 91161daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang private static final int HDMI_DEVICE_UPDATED = 6; 912969167dc05a6485a32d160895871cff46fd81884Wonsik Kim 913969167dc05a6485a32d160895871cff46fd81884Wonsik Kim @Override 914969167dc05a6485a32d160895871cff46fd81884Wonsik Kim public final void handleMessage(Message msg) { 915969167dc05a6485a32d160895871cff46fd81884Wonsik Kim switch (msg.what) { 916187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim case STATE_CHANGED: { 917969167dc05a6485a32d160895871cff46fd81884Wonsik Kim String inputId = (String) msg.obj; 918969167dc05a6485a32d160895871cff46fd81884Wonsik Kim int state = msg.arg1; 919187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mListener.onStateChanged(inputId, state); 920187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim break; 921187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 922187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim case HARDWARE_DEVICE_ADDED: { 923187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim TvInputHardwareInfo info = (TvInputHardwareInfo) msg.obj; 924187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim mListener.onHardwareDeviceAdded(info); 925187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim break; 926187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 927187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim case HARDWARE_DEVICE_REMOVED: { 9284f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee TvInputHardwareInfo info = (TvInputHardwareInfo) msg.obj; 9294f9f57cede3de2e2aa3045e04b485b176ab22dbdJi-Hwan Lee mListener.onHardwareDeviceRemoved(info); 930187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim break; 931187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 932546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo case HDMI_DEVICE_ADDED: { 93361f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang HdmiDeviceInfo info = (HdmiDeviceInfo) msg.obj; 934546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo mListener.onHdmiDeviceAdded(info); 935187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim break; 936187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 937546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo case HDMI_DEVICE_REMOVED: { 93861f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang HdmiDeviceInfo info = (HdmiDeviceInfo) msg.obj; 939546c635ad9a26421fbdf54efa765b5ab0a63c191Jae Seo mListener.onHdmiDeviceRemoved(info); 940969167dc05a6485a32d160895871cff46fd81884Wonsik Kim break; 941969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 94261daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang case HDMI_DEVICE_UPDATED: { 943184a6d69b1dbab8059e4f81d5674adde8e344aa3Wonsik Kim HdmiDeviceInfo info = (HdmiDeviceInfo) msg.obj; 944184a6d69b1dbab8059e4f81d5674adde8e344aa3Wonsik Kim String inputId = null; 945184a6d69b1dbab8059e4f81d5674adde8e344aa3Wonsik Kim synchronized (mLock) { 946184a6d69b1dbab8059e4f81d5674adde8e344aa3Wonsik Kim inputId = mHdmiInputIdMap.get(info.getId()); 947184a6d69b1dbab8059e4f81d5674adde8e344aa3Wonsik Kim } 948184a6d69b1dbab8059e4f81d5674adde8e344aa3Wonsik Kim if (inputId != null) { 949184a6d69b1dbab8059e4f81d5674adde8e344aa3Wonsik Kim mListener.onHdmiDeviceUpdated(inputId, info); 950184a6d69b1dbab8059e4f81d5674adde8e344aa3Wonsik Kim } else { 951184a6d69b1dbab8059e4f81d5674adde8e344aa3Wonsik Kim Slog.w(TAG, "Could not resolve input ID matching the device info; " 952184a6d69b1dbab8059e4f81d5674adde8e344aa3Wonsik Kim + "ignoring."); 953184a6d69b1dbab8059e4f81d5674adde8e344aa3Wonsik Kim } 954184a6d69b1dbab8059e4f81d5674adde8e344aa3Wonsik Kim break; 95561daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang } 956969167dc05a6485a32d160895871cff46fd81884Wonsik Kim default: { 957969167dc05a6485a32d160895871cff46fd81884Wonsik Kim Slog.w(TAG, "Unhandled message: " + msg); 958969167dc05a6485a32d160895871cff46fd81884Wonsik Kim break; 959969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 960969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 961969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 962969167dc05a6485a32d160895871cff46fd81884Wonsik Kim } 963187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim 9647474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim // Listener implementations for HdmiControlService 9657474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim 9667474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim private final class HdmiHotplugEventListener extends IHdmiHotplugEventListener.Stub { 9677474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim @Override 9687474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim public void onReceived(HdmiHotplugEvent event) { 9697474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim synchronized (mLock) { 9707474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim mHdmiStateMap.put(event.getPort(), event.isConnected()); 971d922a546b94119217fb790113d0001cad0432060Wonsik Kim TvInputHardwareInfo hardwareInfo = 972d922a546b94119217fb790113d0001cad0432060Wonsik Kim findHardwareInfoForHdmiPortLocked(event.getPort()); 973d922a546b94119217fb790113d0001cad0432060Wonsik Kim if (hardwareInfo == null) { 974d922a546b94119217fb790113d0001cad0432060Wonsik Kim return; 975d922a546b94119217fb790113d0001cad0432060Wonsik Kim } 976d922a546b94119217fb790113d0001cad0432060Wonsik Kim String inputId = mHardwareInputIdMap.get(hardwareInfo.getDeviceId()); 9777474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim if (inputId == null) { 9787474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim return; 9797474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim } 9807474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim mHandler.obtainMessage(ListenerHandler.STATE_CHANGED, 9817474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim convertConnectedToState(event.isConnected()), 0, inputId).sendToTarget(); 9827474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim } 9837474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim } 9847474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim } 9857474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim 986187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim private final class HdmiDeviceEventListener extends IHdmiDeviceEventListener.Stub { 987187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim @Override 98861daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang public void onStatusChanged(HdmiDeviceInfo deviceInfo, int status) { 989d922a546b94119217fb790113d0001cad0432060Wonsik Kim synchronized (mLock) { 99061daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang int messageType = 0; 991e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim Object obj = null; 99261daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang switch (status) { 99361daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang case HdmiControlManager.DEVICE_EVENT_ADD_DEVICE: { 994cf445877c60396cac1e8ecef75287952d2580db6Jungshik Jang if (findHdmiDeviceInfo(deviceInfo.getId()) == null) { 99561daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang mHdmiDeviceList.add(deviceInfo); 99661daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang } else { 99761daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang Slog.w(TAG, "The list already contains " + deviceInfo + "; ignoring."); 99861daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang return; 99961daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang } 100061daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang messageType = ListenerHandler.HDMI_DEVICE_ADDED; 1001e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim obj = deviceInfo; 100261daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang break; 1003d922a546b94119217fb790113d0001cad0432060Wonsik Kim } 100461daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang case HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE: { 1005cf445877c60396cac1e8ecef75287952d2580db6Jungshik Jang HdmiDeviceInfo originalDeviceInfo = findHdmiDeviceInfo(deviceInfo.getId()); 1006cf445877c60396cac1e8ecef75287952d2580db6Jungshik Jang if (!mHdmiDeviceList.remove(originalDeviceInfo)) { 100761daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang Slog.w(TAG, "The list doesn't contain " + deviceInfo + "; ignoring."); 100861daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang return; 100961daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang } 101061daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang messageType = ListenerHandler.HDMI_DEVICE_REMOVED; 1011e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim obj = deviceInfo; 101261daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang break; 101361daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang } 101461daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang case HdmiControlManager.DEVICE_EVENT_UPDATE_DEVICE: { 1015cf445877c60396cac1e8ecef75287952d2580db6Jungshik Jang HdmiDeviceInfo originalDeviceInfo = findHdmiDeviceInfo(deviceInfo.getId()); 1016cf445877c60396cac1e8ecef75287952d2580db6Jungshik Jang if (!mHdmiDeviceList.remove(originalDeviceInfo)) { 101761daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang Slog.w(TAG, "The list doesn't contain " + deviceInfo + "; ignoring."); 101861daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang return; 101961daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang } 102061daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang mHdmiDeviceList.add(deviceInfo); 102161daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang messageType = ListenerHandler.HDMI_DEVICE_UPDATED; 1022184a6d69b1dbab8059e4f81d5674adde8e344aa3Wonsik Kim obj = deviceInfo; 102361daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang break; 1024d922a546b94119217fb790113d0001cad0432060Wonsik Kim } 1025d922a546b94119217fb790113d0001cad0432060Wonsik Kim } 102661daf6b38e7a7ada2a6ca5a60539a54b9c6810bdJungshik Jang 1027e92f857d50d7259a4cf7ef5b88309e098338c9c1Wonsik Kim Message msg = mHandler.obtainMessage(messageType, 0, 0, obj); 1028d922a546b94119217fb790113d0001cad0432060Wonsik Kim if (findHardwareInfoForHdmiPortLocked(deviceInfo.getPortId()) != null) { 1029d922a546b94119217fb790113d0001cad0432060Wonsik Kim msg.sendToTarget(); 1030d922a546b94119217fb790113d0001cad0432060Wonsik Kim } else { 1031d922a546b94119217fb790113d0001cad0432060Wonsik Kim mPendingHdmiDeviceEvents.add(msg); 1032d922a546b94119217fb790113d0001cad0432060Wonsik Kim } 1033d922a546b94119217fb790113d0001cad0432060Wonsik Kim } 1034187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 1035cf445877c60396cac1e8ecef75287952d2580db6Jungshik Jang 1036cf445877c60396cac1e8ecef75287952d2580db6Jungshik Jang private HdmiDeviceInfo findHdmiDeviceInfo(int id) { 1037cf445877c60396cac1e8ecef75287952d2580db6Jungshik Jang for (HdmiDeviceInfo info : mHdmiDeviceList) { 1038cf445877c60396cac1e8ecef75287952d2580db6Jungshik Jang if (info.getId() == id) { 1039cf445877c60396cac1e8ecef75287952d2580db6Jungshik Jang return info; 1040cf445877c60396cac1e8ecef75287952d2580db6Jungshik Jang } 1041cf445877c60396cac1e8ecef75287952d2580db6Jungshik Jang } 1042cf445877c60396cac1e8ecef75287952d2580db6Jungshik Jang return null; 1043cf445877c60396cac1e8ecef75287952d2580db6Jungshik Jang } 1044187423c0bc4b27479bc8c23bd86969429094b296Wonsik Kim } 10457474faca5bab2fba5749cff7ed15558231307e38Jinsuk Kim 10461f819bbfc80f0ae9de120e9b81250db36629a0b1Jungshik Jang private final class HdmiSystemAudioModeChangeListener extends 10471f819bbfc80f0ae9de120e9b81250db36629a0b1Jungshik Jang IHdmiSystemAudioModeChangeListener.Stub { 10481f819bbfc80f0ae9de120e9b81250db36629a0b1Jungshik Jang @Override 10491f819bbfc80f0ae9de120e9b81250db36629a0b1Jungshik Jang public void onStatusChanged(boolean enabled) throws RemoteException { 10501f819bbfc80f0ae9de120e9b81250db36629a0b1Jungshik Jang synchronized (mLock) { 10511f819bbfc80f0ae9de120e9b81250db36629a0b1Jungshik Jang for (int i = 0; i < mConnections.size(); ++i) { 10521f819bbfc80f0ae9de120e9b81250db36629a0b1Jungshik Jang TvInputHardwareImpl impl = mConnections.valueAt(i).getHardwareImplLocked(); 105344bb3a5bd630cfe0a4813586e840d59b9cbc9f64Jungshik Jang if (impl != null) { 105444bb3a5bd630cfe0a4813586e840d59b9cbc9f64Jungshik Jang impl.handleAudioSinkUpdated(); 105544bb3a5bd630cfe0a4813586e840d59b9cbc9f64Jungshik Jang } 10561f819bbfc80f0ae9de120e9b81250db36629a0b1Jungshik Jang } 10571f819bbfc80f0ae9de120e9b81250db36629a0b1Jungshik Jang } 10581f819bbfc80f0ae9de120e9b81250db36629a0b1Jungshik Jang } 10591f819bbfc80f0ae9de120e9b81250db36629a0b1Jungshik Jang } 1060c22dbb69194c8e8fe2a32326d1f37a738cad0904Wonsik Kim} 1061