ActiveSourceHandler.java revision c0c20d0522d7756d80f011e7a54bf3b51c78df41
1a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim/* 2a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * Copyright (C) 2014 The Android Open Source Project 3a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * 4a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * Licensed under the Apache License, Version 2.0 (the "License"); 5a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * you may not use this file except in compliance with the License. 6a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * You may obtain a copy of the License at 7a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * 8a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * http://www.apache.org/licenses/LICENSE-2.0 9a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * 10a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * Unless required by applicable law or agreed to in writing, software 11a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * distributed under the License is distributed on an "AS IS" BASIS, 12a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * See the License for the specific language governing permissions and 14a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * limitations under the License. 15a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim */ 16a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim 17a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kimpackage com.android.server.hdmi; 18a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim 19a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kimimport android.annotation.Nullable; 20a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kimimport android.hardware.hdmi.IHdmiControlCallback; 21a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kimimport android.hardware.hdmi.HdmiCecDeviceInfo; 22c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kimimport android.hardware.hdmi.HdmiControlManager; 23a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kimimport android.os.RemoteException; 24a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kimimport android.util.Slog; 25a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim 26a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim/** 27a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * Handles CEC command <Active Source>. 2879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * <p> 298333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim * Used by feature actions that need to handle the command in their flow. Only for TV 308333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim * local device. 31a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim */ 32a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kimfinal class ActiveSourceHandler { 33a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim private static final String TAG = "ActiveSourceHandler"; 34a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim 358333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim private final HdmiCecLocalDeviceTv mSource; 36a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim private final HdmiControlService mService; 3779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang @Nullable 3879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang private final IHdmiControlCallback mCallback; 39a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim 408333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim static ActiveSourceHandler create(HdmiCecLocalDeviceTv source, IHdmiControlCallback callback) { 4179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang if (source == null) { 42a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim Slog.e(TAG, "Wrong arguments"); 43a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim return null; 44a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } 4579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return new ActiveSourceHandler(source, callback); 46a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } 47a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim 488333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim private ActiveSourceHandler(HdmiCecLocalDeviceTv source, IHdmiControlCallback callback) { 4979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mSource = source; 5079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mService = mSource.getService(); 51a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim mCallback = callback; 52a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } 53a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim 54a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim /** 55a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * Handles the incoming active source command. 56a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * 578333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim * @param activeAddress logical address of the device to be the active source 588333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim * @param activePath routing path of the device to be the active source 59a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim */ 608333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim void process(int activeAddress, int activePath) { 618333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim // Seq #17 628333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim HdmiCecLocalDeviceTv tv = mSource; 638333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim if (getSourcePath() == activePath && tv.getActiveSource() == getSourceAddress()) { 64c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim invokeCallback(HdmiControlManager.RESULT_SUCCESS); 65a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim return; 66a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } 678333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim HdmiCecDeviceInfo device = mService.getDeviceInfo(activeAddress); 68a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim if (device == null) { 6992b77cf9cbf512e7141cad6fef5a38d0682dde43Jinsuk Kim tv.addAndStartAction(new NewDeviceAction(tv, activeAddress, activePath)); 70a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } 71a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim 728333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim int currentActive = tv.getActiveSource(); 738333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim int currentPath = tv.getActivePath(); 744d43d93743222311c6377d4904c19ccb93699d3bJinsuk Kim if (!tv.isProhibitMode()) { 758333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim tv.updateActiveSource(activeAddress, activePath); 768333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim if (currentActive != activeAddress && currentPath != activePath) { 778333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim tv.updateActivePortId(mService.pathToPortId(activePath)); 78a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } 79c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim invokeCallback(HdmiControlManager.RESULT_SUCCESS); 80a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } else { 81a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim // TV is in a mode that should keep its current source/input from 82a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim // being changed for its operation. Reclaim the active source 83a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim // or switch the port back to the one used for the current mode. 848333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim if (currentActive == getSourceAddress()) { 85a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim HdmiCecMessage activeSource = 868333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim HdmiCecMessageBuilder.buildActiveSource(currentActive, currentPath); 87a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim mService.sendCecCommand(activeSource); 888333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim tv.updateActiveSource(currentActive, currentPath); 89c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim invokeCallback(HdmiControlManager.RESULT_SUCCESS); 90a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } else { 918333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim HdmiCecMessage routingChange = HdmiCecMessageBuilder.buildRoutingChange( 928333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim getSourceAddress(), activePath, currentPath); 938333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim mService.sendCecCommand(routingChange); 9404fd28046acc2ac74339ed94cec76a0bfda846f7Jinsuk Kim tv.addAndStartAction(new RoutingControlAction(tv, currentPath, true, mCallback)); 95a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } 96a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } 97a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } 98a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim 9979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang private final int getSourceAddress() { 10079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mSource.getDeviceInfo().getLogicalAddress(); 10179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 10279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 10379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang private final int getSourcePath() { 10479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mSource.getDeviceInfo().getPhysicalAddress(); 10579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 10679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 107a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim private void invokeCallback(int result) { 108a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim if (mCallback == null) { 109a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim return; 110a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } 111a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim try { 112a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim mCallback.onComplete(result); 113a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } catch (RemoteException e) { 114a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim Slog.e(TAG, "Callback failed:" + e); 115a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } 116a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } 117a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim} 118