HdmiCecFeatureAction.java revision 67ea521d14f366fe5aac09e512865d31bfa0ee53
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.hardware.hdmi.HdmiCecMessage; 19c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kimimport android.os.Handler; 20c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kimimport android.os.Looper; 21c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kimimport android.os.Message; 22c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kimimport android.util.Slog; 23c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 24c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kimimport com.android.internal.annotations.VisibleForTesting; 25c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 26c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim/** 27c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * Encapsulates a sequence of CEC/MHL command exchange for a certain feature. 28c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * 29c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * <p>Many CEC/MHL features are accomplished by CEC devices on the bus exchanging 30c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * more than one command. {@link FeatureAction} represents the life cycle of the communication, 31c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * manages the state as the process progresses, and if necessary, returns the result 32c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * to the caller which initiates the action, through the callback given at the creation 33c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * of the object. All the actual action classes inherit FeatureAction. 34c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * 35c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * <p>More than one FeatureAction objects can be up and running simultaneously, 36c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * maintained by {@link HdmiControlService}. Each action is passed a new command 37c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * arriving from the bus, and either consumes it if the command is what the action expects, 38c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * or yields it to other action. 39c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * 40c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * Declared as package private, accessed by {@link HdmiControlService} only. 41c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim */ 42c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kimabstract class FeatureAction { 43c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 44c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim private static final String TAG = "FeatureAction"; 45c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 46c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim // Timer handler message used for timeout event 47c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim protected static final int MSG_TIMEOUT = 100; 48c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 49c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim // Default timeout for the incoming command to arrive in response to a request 50c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim protected static final int TIMEOUT_MS = 1000; 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 58c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim protected final HdmiControlService mService; 59c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 60c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim // Logical address of the device for which the feature action is taken. The commands 61c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim // generated in an action all use this field as source address. 62c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim protected final int mSourceAddress; 63c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 64c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim // Timer that manages timeout events. 65c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim protected ActionTimer mActionTimer; 66c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 67c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim FeatureAction(HdmiControlService service, int sourceAddress) { 68c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim mService = service; 69c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim mSourceAddress = sourceAddress; 70c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim mActionTimer = createActionTimer(service.getServiceLooper()); 71c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 72c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 73c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim @VisibleForTesting 74c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim void setActionTimer(ActionTimer actionTimer) { 75c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim mActionTimer = actionTimer; 76c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 77c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 78c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim /** 79c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * Called right after the action is created. Initialization or first step to take 80c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * for the action can be done in this method. 81c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * 82c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * @return true if the operation is successful; otherwise false. 83c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim */ 84c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim abstract boolean start(); 85c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 86c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim /** 87c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * Process the command. Called whenever a new command arrives. 88c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * 89c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * @param cmd command to process 90c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * @return true if the command was consumed in the process; Otherwise false, which 91c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * indicates that the command shall be handled by other actions. 92c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim */ 93c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim abstract boolean processCommand(HdmiCecMessage cmd); 94c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 95c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim /** 96c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * Called when the action should handle the timer event it created before. 97c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * 98c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * <p>CEC standard mandates each command transmission should be responded within 99c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * certain period of time. The method is called when the timer it created as it transmitted 100c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * a command gets expired. Inner logic should take an appropriate action. 101c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * 102c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * @param state the state associated with the time when the timer was created 103c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim */ 104c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim abstract void handleTimerEvent(int state); 105c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 106c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim /** 107c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * Timer handler interface used for FeatureAction classes. 108c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim */ 109c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim interface ActionTimer { 110c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim /** 111c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * Send a timer message. 112c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * 113c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * Also carries the state of the action when the timer is created. Later this state is 114c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * compared to the one the action is in when it receives the timer to let the action tell 115c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * the right timer to handle. 116c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * 117c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * @param state state of the action is in 118c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * @param delayMillis amount of delay for the timer 119c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim */ 120c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim void sendTimerMessage(int state, long delayMillis); 12167ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 12267ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang /** 12367ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * Removes any pending timer message. 12467ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang */ 12567ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang void clearTimerMessage(); 126c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 127c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 128c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim private class ActionTimerHandler extends Handler implements ActionTimer { 129c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 130c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim public ActionTimerHandler(Looper looper) { 131c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim super(looper); 132c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 133c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 134c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim @Override 135c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim public void sendTimerMessage(int state, long delayMillis) { 136c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim sendMessageDelayed(obtainMessage(MSG_TIMEOUT, state), 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 16767ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang protected final boolean sendCommand(HdmiCecMessage cmd) { 16867ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang return mService.sendCecCommand(cmd); 16967ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 17067ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 17167ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang /** 17267ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * Clean up action's state. 17367ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * 17467ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * <p>Declared as package-private. Only {@link HdmiControlService} can access it. 17567ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang */ 17667ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang void clear() { 17767ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang mState = STATE_NONE; 17867ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang // Clear all timers. 17967ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang mActionTimer.clearTimerMessage(); 180c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 181c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 182c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim /** 183c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * Finish up the action. Reset the state, and remove itself from the action queue. 184c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim */ 185c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim protected void finish() { 18667ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang clear(); 187c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim removeAction(this); 188c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 189c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim 190c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim /** 191c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * Remove the action from the action queue. This is called after the action finishes 192c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * its role. 193c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * 194c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim * @param action 195c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim */ 196c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim private void removeAction(FeatureAction action) { 197c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim mService.removeAction(action); 198c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim } 199c70d2295dd3fb87ce8c81c704688d1ad05043b4dJinsuk Kim} 200