HdmiCecFeatureAction.java revision c516d65fd96cdc39f9935ddb80d26ee6499a77bf
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/** 31c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * Encapsulates a sequence of CEC/MHL command exchange for a certain feature. 32c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * 33c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * <p>Many CEC/MHL features are accomplished by CEC devices on the bus exchanging 34c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * more than one command. {@link FeatureAction} represents the life cycle of the communication, 35c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * manages the state as the process progresses, and if necessary, returns the result 36c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * to the caller which initiates the action, through the callback given at the creation 37c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * of the object. All the actual action classes inherit FeatureAction. 38c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * 39c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * <p>More than one FeatureAction objects can be up and running simultaneously, 4079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * maintained by {@link HdmiCecLocalDevice}. Each action is passed a new command 41c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * arriving from the bus, and either consumes it if the command is what the action expects, 42c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * or yields it to other action. 43c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * 44c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * Declared as package private, accessed by {@link HdmiControlService} only. 45c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim */ 46c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kimabstract class FeatureAction { 47c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim private static final String TAG = "FeatureAction"; 48c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 49c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim // Timer handler message used for timeout event 50c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim protected static final int MSG_TIMEOUT = 100; 51c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 52c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim // Default state used in common by all the feature actions. 53c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim protected static final int STATE_NONE = 0; 54c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 55c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim // Internal state indicating the progress of action. 56c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim protected int mState = STATE_NONE; 57c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 5879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang private final HdmiControlService mService; 5979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang private final HdmiCecLocalDevice mSource; 60c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 61c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim // Timer that manages timeout events. 62c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim protected ActionTimer mActionTimer; 63c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 64c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo private ArrayList<Pair<FeatureAction, Runnable>> mOnFinishedCallbacks; 65c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo 6679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang FeatureAction(HdmiCecLocalDevice source) { 6779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mSource = source; 6879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mService = mSource.getService(); 6979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mActionTimer = createActionTimer(mService.getServiceLooper()); 70c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 71c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 72c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim @VisibleForTesting 73c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim void setActionTimer(ActionTimer actionTimer) { 74c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim mActionTimer = actionTimer; 75c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 76c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 77c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim /** 78c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * Called right after the action is created. Initialization or first step to take 79c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * for the action can be done in this method. 80c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * 81c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * @return true if the operation is successful; otherwise false. 82c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim */ 83c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim abstract boolean start(); 84c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 85c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim /** 86c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * Process the command. Called whenever a new command arrives. 87c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * 88c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * @param cmd command to process 89c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * @return true if the command was consumed in the process; Otherwise false, which 90c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * indicates that the command shall be handled by other actions. 91c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim */ 92c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim abstract boolean processCommand(HdmiCecMessage cmd); 93c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 94c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim /** 95c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * Called when the action should handle the timer event it created before. 96c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * 97c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * <p>CEC standard mandates each command transmission should be responded within 98c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * certain period of time. The method is called when the timer it created as it transmitted 99c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * a command gets expired. Inner logic should take an appropriate action. 100c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * 101c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * @param state the state associated with the time when the timer was created 102c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim */ 103c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim abstract void handleTimerEvent(int state); 104c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 105c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim /** 106c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * Timer handler interface used for FeatureAction classes. 107c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim */ 108c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim interface ActionTimer { 109c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim /** 110c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * Send a timer message. 111c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * 112c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * Also carries the state of the action when the timer is created. Later this state is 113c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * compared to the one the action is in when it receives the timer to let the action tell 114c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * the right timer to handle. 115c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * 116c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * @param state state of the action is in 117c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * @param delayMillis amount of delay for the timer 118c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim */ 119c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim void sendTimerMessage(int state, long delayMillis); 12067ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 12167ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang /** 12267ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * Removes any pending timer message. 12367ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang */ 12467ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang void clearTimerMessage(); 125c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 126c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 127c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim private class ActionTimerHandler extends Handler implements ActionTimer { 128c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 129c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim public ActionTimerHandler(Looper looper) { 130c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim super(looper); 131c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 132c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 133c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim @Override 134c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim public void sendTimerMessage(int state, long delayMillis) { 135b0674f0f7c04b707ca7b11f5700bdb9e51b61872Jinsuk Kim // The third argument(0) is not used. 136b0674f0f7c04b707ca7b11f5700bdb9e51b61872Jinsuk Kim sendMessageDelayed(obtainMessage(MSG_TIMEOUT, state, 0), delayMillis); 137c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 138c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 139c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim @Override 14067ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang public void clearTimerMessage() { 14167ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang removeMessages(MSG_TIMEOUT); 14267ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 14367ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 14467ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang @Override 145c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim public void handleMessage(Message msg) { 146c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim switch (msg.what) { 147c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim case MSG_TIMEOUT: 148c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim handleTimerEvent(msg.arg1); 149c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim break; 150c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim default: 151c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim Slog.w(TAG, "Unsupported message:" + msg.what); 152c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim break; 153c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 154c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 155c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 156c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 157c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim private ActionTimer createActionTimer(Looper looper) { 158c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim return new ActionTimerHandler(looper); 159c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 160c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 161c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim // Add a new timer. The timer event will come to mActionTimer.handleMessage() in 162c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim // delayMillis. 163c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim protected void addTimer(int state, int delayMillis) { 164c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim mActionTimer.sendTimerMessage(state, delayMillis); 165c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 166c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 167d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang protected final void sendCommand(HdmiCecMessage cmd) { 168d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang mService.sendCecCommand(cmd); 169d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang } 170d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang 171d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang protected final void sendCommand(HdmiCecMessage cmd, 172d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang HdmiControlService.SendMessageCallback callback) { 173d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang mService.sendCecCommand(cmd, callback); 17467ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 17567ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 17679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected final void addAndStartAction(FeatureAction action) { 17779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mSource.addAndStartAction(action); 17879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 17979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 18079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected final <T extends FeatureAction> List<T> getActions(final Class<T> clazz) { 18179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mSource.getActions(clazz); 18279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 18379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 18479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected final HdmiCecMessageCache getCecMessageCache() { 18579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mSource.getCecMessageCache(); 18679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 18779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 18879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang /** 18979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * Remove the action from the action queue. This is called after the action finishes 19079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * its role. 19179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * 19279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * @param action 19379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang */ 19479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected final void removeAction(FeatureAction action) { 19579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mSource.removeAction(action); 19679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 19779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 19879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected final <T extends FeatureAction> void removeAction(final Class<T> clazz) { 19979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mSource.removeActionExcept(clazz, null); 20079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 20179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 20279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected final <T extends FeatureAction> void removeActionExcept(final Class<T> clazz, 20379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang final FeatureAction exception) { 20479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mSource.removeActionExcept(clazz, exception); 20579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 20679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 20779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected final void pollDevices(DevicePollingCallback callback, int pickStrategy, 20879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang int retryCount) { 2091de514256fd3015cf45256f3198ab5472024af9bJungshik Jang mService.pollDevices(callback, getSourceAddress(), pickStrategy, retryCount); 21079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 21179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 21267ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang /** 21367ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * Clean up action's state. 21467ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * 21567ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * <p>Declared as package-private. Only {@link HdmiControlService} can access it. 21667ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang */ 21767ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang void clear() { 21867ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang mState = STATE_NONE; 21967ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang // Clear all timers. 22067ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang mActionTimer.clearTimerMessage(); 221c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 222c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 223c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim /** 224c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * Finish up the action. Reset the state, and remove itself from the action queue. 225c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim */ 226c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim protected void finish() { 227c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo finish(true); 228c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo } 229c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo 230c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo void finish(boolean removeSelf) { 23167ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang clear(); 232c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo if (removeSelf) { 233c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo removeAction(this); 234c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo } 235c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo if (mOnFinishedCallbacks != null) { 236c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo for (Pair<FeatureAction, Runnable> actionCallbackPair: mOnFinishedCallbacks) { 237c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo if (actionCallbackPair.first.mState != STATE_NONE) { 238c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo actionCallbackPair.second.run(); 239c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo } 240c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo } 241c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo mOnFinishedCallbacks = null; 242c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo } 243c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 244c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 24579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected final HdmiCecLocalDevice localDevice() { 24679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mSource; 24779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 24879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 24979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected final HdmiCecLocalDevicePlayback playback() { 25079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return (HdmiCecLocalDevicePlayback) mSource; 25179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 25279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 25379c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected final HdmiCecLocalDeviceTv tv() { 25479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return (HdmiCecLocalDeviceTv) mSource; 25579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 25679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 25779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected final int getSourceAddress() { 25879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mSource.getDeviceInfo().getLogicalAddress(); 25979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang } 26079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang 26179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang protected final int getSourcePath() { 26279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang return mSource.getDeviceInfo().getPhysicalAddress(); 263c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 2648fa36b110be29d92a9aba070fa4666eefb14b584Jungshik Jang 265c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo protected final void sendUserControlPressedAndReleased(int targetAddress, int uiCommand) { 2668fa36b110be29d92a9aba070fa4666eefb14b584Jungshik Jang sendCommand(HdmiCecMessageBuilder.buildUserControlPressed( 2678fa36b110be29d92a9aba070fa4666eefb14b584Jungshik Jang getSourceAddress(), targetAddress, uiCommand)); 2688fa36b110be29d92a9aba070fa4666eefb14b584Jungshik Jang sendCommand(HdmiCecMessageBuilder.buildUserControlReleased( 2698fa36b110be29d92a9aba070fa4666eefb14b584Jungshik Jang getSourceAddress(), targetAddress)); 2708fa36b110be29d92a9aba070fa4666eefb14b584Jungshik Jang } 271c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo 272c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo protected final void addOnFinishedCallback(FeatureAction action, Runnable runnable) { 273c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo if (mOnFinishedCallbacks == null) { 274c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo mOnFinishedCallbacks = new ArrayList<>(); 275c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo } 276c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo mOnFinishedCallbacks.add(Pair.create(action, runnable)); 277c516d65fd96cdc39f9935ddb80d26ee6499a77bfYuncheol Heo } 278c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim} 279