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; 2161f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jangimport android.hardware.hdmi.HdmiDeviceInfo; 22c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kimimport android.hardware.hdmi.HdmiControlManager; 23a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kimimport android.os.RemoteException; 24a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kimimport android.util.Slog; 25a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim 2672b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kimimport com.android.server.hdmi.HdmiCecLocalDevice.ActiveSource; 2772b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim 28a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim/** 29a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * Handles CEC command <Active Source>. 3079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * <p> 318333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim * Used by feature actions that need to handle the command in their flow. Only for TV 328333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim * local device. 33a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim */ 34a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kimfinal class ActiveSourceHandler { 35a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim private static final String TAG = "ActiveSourceHandler"; 36a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim 378333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim private final HdmiCecLocalDeviceTv mSource; 38a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim private final HdmiControlService mService; 3979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang @Nullable 4079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang private final IHdmiControlCallback mCallback; 41a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim 428333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim static ActiveSourceHandler create(HdmiCecLocalDeviceTv source, IHdmiControlCallback callback) { 4379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang if (source == null) { 44a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim Slog.e(TAG, "Wrong arguments"); 45a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim return null; 46a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } 4779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return new ActiveSourceHandler(source, callback); 48a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } 49a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim 508333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim private ActiveSourceHandler(HdmiCecLocalDeviceTv source, IHdmiControlCallback callback) { 5179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mSource = source; 5279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mService = mSource.getService(); 53a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim mCallback = callback; 54a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } 55a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim 56a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim /** 57a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * Handles the incoming active source command. 58a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim * 5972b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim * @param newActive new active source information 60bdf27fbf746bee11430c4db2ea6dfd026bae77feJinsuk Kim * @param deviceType device type of the new active source 61a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim */ 62bdf27fbf746bee11430c4db2ea6dfd026bae77feJinsuk Kim void process(ActiveSource newActive, int deviceType) { 638333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim // Seq #17 648333571bd5e0a08773a1679964f8d96227af3356Jinsuk Kim HdmiCecLocalDeviceTv tv = mSource; 6561f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang HdmiDeviceInfo device = mService.getDeviceInfo(newActive.logicalAddress); 66a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim if (device == null) { 67bdf27fbf746bee11430c4db2ea6dfd026bae77feJinsuk Kim tv.startNewDeviceAction(newActive, deviceType); 68a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } 69a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim 704d43d93743222311c6377d4904c19ccb93699d3bJinsuk Kim if (!tv.isProhibitMode()) { 7172b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim tv.updateActiveSource(newActive); 727c3a95633d307c4be30c9dbbf1071063aa7a3c64Jinsuk Kim boolean notifyInputChange = (mCallback == null); 737c3a95633d307c4be30c9dbbf1071063aa7a3c64Jinsuk Kim tv.updateActiveInput(newActive.physicalAddress, notifyInputChange); 74c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim invokeCallback(HdmiControlManager.RESULT_SUCCESS); 75a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } else { 76a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim // TV is in a mode that should keep its current source/input from 77a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim // being changed for its operation. Reclaim the active source 78a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim // or switch the port back to the one used for the current mode. 797c3a95633d307c4be30c9dbbf1071063aa7a3c64Jinsuk Kim ActiveSource current = tv.getActiveSource(); 8072b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim if (current.logicalAddress == getSourceAddress()) { 8172b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim HdmiCecMessage activeSourceCommand = HdmiCecMessageBuilder.buildActiveSource( 8272b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim current.logicalAddress, current.physicalAddress); 8372b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim mService.sendCecCommand(activeSourceCommand); 8472b7d738d5b9254594726304cdb1777b54d95631Jinsuk Kim tv.updateActiveSource(current); 85c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim invokeCallback(HdmiControlManager.RESULT_SUCCESS); 86a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } else { 87546d867cb89099ed9036d54d1d49e11748c9a27eJinsuk Kim tv.startRoutingControl(newActive.physicalAddress, current.physicalAddress, true, 88546d867cb89099ed9036d54d1d49e11748c9a27eJinsuk Kim mCallback); 89a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } 90a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } 91a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } 92a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim 9379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang private final int getSourceAddress() { 9479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mSource.getDeviceInfo().getLogicalAddress(); 9579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 9679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 97a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim private void invokeCallback(int result) { 98a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim if (mCallback == null) { 99a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim return; 100a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } 101a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim try { 102a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim mCallback.onComplete(result); 103a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } catch (RemoteException e) { 104a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim Slog.e(TAG, "Callback failed:" + e); 105a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } 106a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim } 107a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim} 108