1c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim/* 2c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * Copyright (C) 2014 The Android Open Source Project 3c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * 4c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * Licensed under the Apache License, Version 2.0 (the "License"); 5c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * you may not use this file except in compliance with the License. 6c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * You may obtain a copy of the License at 7c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * 8c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * http://www.apache.org/licenses/LICENSE-2.0 9c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * 10c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * Unless required by applicable law or agreed to in writing, software 11c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * distributed under the License is distributed on an "AS IS" BASIS, 12c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * See the License for the specific language governing permissions and 14c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * limitations under the License. 15c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim */ 16c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kimpackage com.android.server.hdmi; 17c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 18c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kimimport android.os.Handler; 19c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kimimport android.os.Looper; 20c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kimimport android.os.Message; 21c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heoimport android.util.Pair; 22c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kimimport android.util.Slog; 23c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 24c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kimimport com.android.internal.annotations.VisibleForTesting; 2579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jangimport com.android.server.hdmi.HdmiControlService.DevicePollingCallback; 2679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 27c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heoimport java.util.ArrayList; 2879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jangimport java.util.List; 29c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 30c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim/** 317df52862dae1fa33c84725c613b0d9b88c1b28b6Jungshik Jang * Encapsulates a sequence of CEC command exchange for a certain feature. 32b509c2ecd99619248b7a07fb0fa978bb27f25cc3Jungshik Jang * <p> 337df52862dae1fa33c84725c613b0d9b88c1b28b6Jungshik Jang * Many CEC features are accomplished by CEC devices on the bus exchanging more than one 34b509c2ecd99619248b7a07fb0fa978bb27f25cc3Jungshik Jang * command. {@link HdmiCecFeatureAction} represents the life cycle of the communication, manages the 35b509c2ecd99619248b7a07fb0fa978bb27f25cc3Jungshik Jang * state as the process progresses, and if necessary, returns the result to the caller which 36b509c2ecd99619248b7a07fb0fa978bb27f25cc3Jungshik Jang * initiates the action, through the callback given at the creation of the object. All the actual 37b509c2ecd99619248b7a07fb0fa978bb27f25cc3Jungshik Jang * action classes inherit FeatureAction. 38b509c2ecd99619248b7a07fb0fa978bb27f25cc3Jungshik Jang * <p> 39b509c2ecd99619248b7a07fb0fa978bb27f25cc3Jungshik Jang * More than one FeatureAction objects can be up and running simultaneously, maintained by 40b509c2ecd99619248b7a07fb0fa978bb27f25cc3Jungshik Jang * {@link HdmiCecLocalDevice}. Each action is passed a new command arriving from the bus, and either 41b509c2ecd99619248b7a07fb0fa978bb27f25cc3Jungshik Jang * consumes it if the command is what the action expects, or yields it to other action. Declared as 42b509c2ecd99619248b7a07fb0fa978bb27f25cc3Jungshik Jang * package private, accessed by {@link HdmiControlService} only. 43c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim */ 44b509c2ecd99619248b7a07fb0fa978bb27f25cc3Jungshik Jangabstract class HdmiCecFeatureAction { 457df52862dae1fa33c84725c613b0d9b88c1b28b6Jungshik Jang private static final String TAG = "HdmiCecFeatureAction"; 46c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 47c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim // Timer handler message used for timeout event 48c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim protected static final int MSG_TIMEOUT = 100; 49c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 50c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim // Default state used in common by all the feature actions. 51c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim protected static final int STATE_NONE = 0; 52c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 53c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim // Internal state indicating the progress of action. 54c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim protected int mState = STATE_NONE; 55c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 5679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang private final HdmiControlService mService; 5779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang private final HdmiCecLocalDevice mSource; 58c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 59c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim // Timer that manages timeout events. 60c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim protected ActionTimer mActionTimer; 61c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 62b509c2ecd99619248b7a07fb0fa978bb27f25cc3Jungshik Jang private ArrayList<Pair<HdmiCecFeatureAction, Runnable>> mOnFinishedCallbacks; 63c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo 64b509c2ecd99619248b7a07fb0fa978bb27f25cc3Jungshik Jang HdmiCecFeatureAction(HdmiCecLocalDevice source) { 6579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mSource = source; 6679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mService = mSource.getService(); 6779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mActionTimer = createActionTimer(mService.getServiceLooper()); 68c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 69c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 70c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim @VisibleForTesting 71c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim void setActionTimer(ActionTimer actionTimer) { 72c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim mActionTimer = actionTimer; 73c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 74c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 75c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim /** 766f87b4e6b6db76cb32d449ad1fdf1946ff4e96f7Jinsuk Kim * Called after the action is created. Initialization or first step to take 776f87b4e6b6db76cb32d449ad1fdf1946ff4e96f7Jinsuk Kim * for the action can be done in this method. Shall update {@code mState} to 786f87b4e6b6db76cb32d449ad1fdf1946ff4e96f7Jinsuk Kim * indicate that the action has started. 79c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * 80c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * @return true if the operation is successful; otherwise false. 81c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim */ 82c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim abstract boolean start(); 83c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 84c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim /** 85c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * Process the command. Called whenever a new command arrives. 86c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * 87c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * @param cmd command to process 885352081c662299b618335bf3024058fa04ef2dfdJungshik Jang * @return true if the command was consumed in the process; Otherwise false. 89c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim */ 90c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim abstract boolean processCommand(HdmiCecMessage cmd); 91c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 92c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim /** 93c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * Called when the action should handle the timer event it created before. 94c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * 95c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * <p>CEC standard mandates each command transmission should be responded within 96c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * certain period of time. The method is called when the timer it created as it transmitted 97c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * a command gets expired. Inner logic should take an appropriate action. 98c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * 99c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * @param state the state associated with the time when the timer was created 100c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim */ 101c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim abstract void handleTimerEvent(int state); 102c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 103c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim /** 104c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * Timer handler interface used for FeatureAction classes. 105c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim */ 106c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim interface ActionTimer { 107c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim /** 108c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * Send a timer message. 109c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * 110c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * Also carries the state of the action when the timer is created. Later this state is 111c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * compared to the one the action is in when it receives the timer to let the action tell 112c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * the right timer to handle. 113c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * 114c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * @param state state of the action is in 115c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * @param delayMillis amount of delay for the timer 116c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim */ 117c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim void sendTimerMessage(int state, long delayMillis); 11867ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 11967ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang /** 12067ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * Removes any pending timer message. 12167ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang */ 12267ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang void clearTimerMessage(); 123c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 124c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 125c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim private class ActionTimerHandler extends Handler implements ActionTimer { 126c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 127c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim public ActionTimerHandler(Looper looper) { 128c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim super(looper); 129c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 130c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 131c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim @Override 132c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim public void sendTimerMessage(int state, long delayMillis) { 133b0674f0f7c04b707ca7b11f5700bdb9e51b61872Jinsuk Kim // The third argument(0) is not used. 134b0674f0f7c04b707ca7b11f5700bdb9e51b61872Jinsuk Kim sendMessageDelayed(obtainMessage(MSG_TIMEOUT, state, 0), delayMillis); 135c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 136c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 137c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim @Override 13867ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang public void clearTimerMessage() { 13967ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang removeMessages(MSG_TIMEOUT); 14067ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 14167ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 14267ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang @Override 143c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim public void handleMessage(Message msg) { 144c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim switch (msg.what) { 145c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim case MSG_TIMEOUT: 146c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim handleTimerEvent(msg.arg1); 147c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim break; 148c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim default: 149c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim Slog.w(TAG, "Unsupported message:" + msg.what); 150c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim break; 151c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 152c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 153c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 154c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 155c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim private ActionTimer createActionTimer(Looper looper) { 156c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim return new ActionTimerHandler(looper); 157c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 158c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 159c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim // Add a new timer. The timer event will come to mActionTimer.handleMessage() in 160c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim // delayMillis. 161c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim protected void addTimer(int state, int delayMillis) { 162c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim mActionTimer.sendTimerMessage(state, delayMillis); 163c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 164c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 1656f87b4e6b6db76cb32d449ad1fdf1946ff4e96f7Jinsuk Kim boolean started() { 1666f87b4e6b6db76cb32d449ad1fdf1946ff4e96f7Jinsuk Kim return mState != STATE_NONE; 1676f87b4e6b6db76cb32d449ad1fdf1946ff4e96f7Jinsuk Kim } 1686f87b4e6b6db76cb32d449ad1fdf1946ff4e96f7Jinsuk Kim 169d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang protected final void sendCommand(HdmiCecMessage cmd) { 170d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang mService.sendCecCommand(cmd); 171d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang } 172d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang 173d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang protected final void sendCommand(HdmiCecMessage cmd, 174d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang HdmiControlService.SendMessageCallback callback) { 175d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang mService.sendCecCommand(cmd, callback); 17667ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 17767ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 178b509c2ecd99619248b7a07fb0fa978bb27f25cc3Jungshik Jang protected final void addAndStartAction(HdmiCecFeatureAction action) { 17979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mSource.addAndStartAction(action); 18079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 18179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 182b509c2ecd99619248b7a07fb0fa978bb27f25cc3Jungshik Jang protected final <T extends HdmiCecFeatureAction> List<T> getActions(final Class<T> clazz) { 18379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mSource.getActions(clazz); 18479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 18579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 18679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected final HdmiCecMessageCache getCecMessageCache() { 18779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mSource.getCecMessageCache(); 18879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 18979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 19079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang /** 19179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * Remove the action from the action queue. This is called after the action finishes 19279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * its role. 19379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * 19479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * @param action 19579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang */ 196b509c2ecd99619248b7a07fb0fa978bb27f25cc3Jungshik Jang protected final void removeAction(HdmiCecFeatureAction action) { 19779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mSource.removeAction(action); 19879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 19979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 200b509c2ecd99619248b7a07fb0fa978bb27f25cc3Jungshik Jang protected final <T extends HdmiCecFeatureAction> void removeAction(final Class<T> clazz) { 20179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mSource.removeActionExcept(clazz, null); 20279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 20379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 204b509c2ecd99619248b7a07fb0fa978bb27f25cc3Jungshik Jang protected final <T extends HdmiCecFeatureAction> void removeActionExcept(final Class<T> clazz, 205b509c2ecd99619248b7a07fb0fa978bb27f25cc3Jungshik Jang final HdmiCecFeatureAction exception) { 20679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mSource.removeActionExcept(clazz, exception); 20779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 20879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 20979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected final void pollDevices(DevicePollingCallback callback, int pickStrategy, 21079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang int retryCount) { 2111de514256fd3015cf45256f3198ab5472024af9bJungshik Jang mService.pollDevices(callback, getSourceAddress(), pickStrategy, retryCount); 21279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 21379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 21467ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang /** 21567ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * Clean up action's state. 21667ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * 21767ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * <p>Declared as package-private. Only {@link HdmiControlService} can access it. 21867ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang */ 21967ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang void clear() { 22067ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang mState = STATE_NONE; 22167ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang // Clear all timers. 22267ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang mActionTimer.clearTimerMessage(); 223c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 224c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 225c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim /** 226c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * Finish up the action. Reset the state, and remove itself from the action queue. 227c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim */ 228c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim protected void finish() { 229c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo finish(true); 230c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo } 231c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo 232c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo void finish(boolean removeSelf) { 23367ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang clear(); 234c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo if (removeSelf) { 235c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo removeAction(this); 236c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo } 237c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo if (mOnFinishedCallbacks != null) { 238b509c2ecd99619248b7a07fb0fa978bb27f25cc3Jungshik Jang for (Pair<HdmiCecFeatureAction, Runnable> actionCallbackPair: mOnFinishedCallbacks) { 239c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo if (actionCallbackPair.first.mState != STATE_NONE) { 240c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo actionCallbackPair.second.run(); 241c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo } 242c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo } 243c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo mOnFinishedCallbacks = null; 244c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo } 245c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 246c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 24779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected final HdmiCecLocalDevice localDevice() { 24879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mSource; 24979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 25079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 25179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected final HdmiCecLocalDevicePlayback playback() { 25279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return (HdmiCecLocalDevicePlayback) mSource; 25379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 25479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 25579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected final HdmiCecLocalDeviceTv tv() { 25679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return (HdmiCecLocalDeviceTv) mSource; 25779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 25879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 25979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected final int getSourceAddress() { 26079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mSource.getDeviceInfo().getLogicalAddress(); 26179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 26279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 26379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected final int getSourcePath() { 26479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mSource.getDeviceInfo().getPhysicalAddress(); 265c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 2668fa36b110be29d92a9aba070fa4666eefb14b584Jungshik Jang 267c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo protected final void sendUserControlPressedAndReleased(int targetAddress, int uiCommand) { 2682e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang mSource.sendUserControlPressedAndReleased(targetAddress, uiCommand); 2698fa36b110be29d92a9aba070fa4666eefb14b584Jungshik Jang } 270c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo 271b509c2ecd99619248b7a07fb0fa978bb27f25cc3Jungshik Jang protected final void addOnFinishedCallback(HdmiCecFeatureAction action, Runnable runnable) { 272c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo if (mOnFinishedCallbacks == null) { 273c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo mOnFinishedCallbacks = new ArrayList<>(); 274c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo } 275c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo mOnFinishedCallbacks.add(Pair.create(action, runnable)); 276c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo } 277c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim} 278