HdmiCecStandbyModeHandler.java revision 25c20298ad04e0e591e0cfdc0bb9d01a985433ab
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.hdmi; 18 19import android.util.SparseArray; 20 21/** 22 * This class handles the incoming messages when HdmiCecService is in the standby mode. 23 */ 24public final class HdmiCecStandbyModeHandler { 25 26 private interface CecMessageHandler { 27 boolean handle(HdmiCecMessage message); 28 } 29 30 private static final class Bystander implements CecMessageHandler { 31 @Override 32 public boolean handle(HdmiCecMessage message) { 33 return true; 34 } 35 } 36 37 private static final class Bypasser implements CecMessageHandler { 38 @Override 39 public boolean handle(HdmiCecMessage message) { 40 return false; 41 } 42 } 43 44 private final class Aborter implements CecMessageHandler { 45 private final int mReason; 46 public Aborter(int reason) { 47 mReason = reason; 48 } 49 @Override 50 public boolean handle(HdmiCecMessage message) { 51 int src = message.getSource(); 52 int dest = message.getDestination(); 53 if (src == Constants.ADDR_BROADCAST || dest == Constants.ADDR_BROADCAST) { 54 // Do not send <Feature Abort> on the message from the unassigned device 55 // or the broadcasted message. 56 return true; 57 } 58 HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildFeatureAbortCommand( 59 dest, src, message.getOpcode(), mReason); 60 mService.sendCecCommand(cecMessage); 61 return true; 62 } 63 } 64 65 private final class AutoOnHandler implements CecMessageHandler { 66 @Override 67 public boolean handle(HdmiCecMessage message) { 68 if (!mTv.getAutoWakeup()) { 69 mAborterRefused.handle(message); 70 return true; 71 } 72 return false; 73 } 74 } 75 76 private final class UserControlProcessedHandler implements CecMessageHandler { 77 @Override 78 public boolean handle(HdmiCecMessage message) { 79 // The power status here is always standby. 80 if (HdmiCecLocalDevice.isPowerOnOrToggleCommand(message)) { 81 return false; 82 } else if (HdmiCecLocalDevice.isPowerOffOrToggleCommand(message)) { 83 return true; 84 } 85 return mAborterIncorrectMode.handle(message); 86 } 87 } 88 89 private final HdmiControlService mService; 90 private final HdmiCecLocalDeviceTv mTv; 91 92 private final SparseArray<CecMessageHandler> mCecMessageHandlers = new SparseArray<>(); 93 private final CecMessageHandler mDefaultHandler = new Aborter( 94 Constants.ABORT_UNRECOGNIZED_OPCODE); 95 private final CecMessageHandler mAborterIncorrectMode = new Aborter( 96 Constants.ABORT_NOT_IN_CORRECT_MODE); 97 private final CecMessageHandler mAborterRefused = new Aborter(Constants.ABORT_REFUSED); 98 private final CecMessageHandler mAutoOnHandler = new AutoOnHandler(); 99 private final CecMessageHandler mBypasser = new Bypasser(); 100 private final CecMessageHandler mBystander = new Bystander(); 101 private final UserControlProcessedHandler 102 mUserControlProcessedHandler = new UserControlProcessedHandler(); 103 104 public HdmiCecStandbyModeHandler(HdmiControlService service, HdmiCecLocalDeviceTv tv) { 105 mService = service; 106 mTv = tv; 107 108 addHandler(Constants.MESSAGE_IMAGE_VIEW_ON, mAutoOnHandler); 109 addHandler(Constants.MESSAGE_TEXT_VIEW_ON, mAutoOnHandler); 110 111 addHandler(Constants.MESSAGE_ACTIVE_SOURCE, mBystander); 112 addHandler(Constants.MESSAGE_REQUEST_ACTIVE_SOURCE, mBystander); 113 addHandler(Constants.MESSAGE_ROUTING_CHANGE, mBystander); 114 addHandler(Constants.MESSAGE_ROUTING_INFORMATION, mBystander); 115 addHandler(Constants.MESSAGE_SET_STREAM_PATH, mBystander); 116 addHandler(Constants.MESSAGE_STANDBY, mBystander); 117 addHandler(Constants.MESSAGE_SET_MENU_LANGUAGE, mBystander); 118 addHandler(Constants.MESSAGE_DEVICE_VENDOR_ID, mBystander); 119 addHandler(Constants.MESSAGE_USER_CONTROL_RELEASED, mBystander); 120 addHandler(Constants.MESSAGE_REPORT_POWER_STATUS, mBystander); 121 addHandler(Constants.MESSAGE_FEATURE_ABORT, mBystander); 122 addHandler(Constants.MESSAGE_INACTIVE_SOURCE, mBystander); 123 addHandler(Constants.MESSAGE_SYSTEM_AUDIO_MODE_STATUS, mBystander); 124 addHandler(Constants.MESSAGE_REPORT_AUDIO_STATUS, mBystander); 125 126 // If TV supports the following messages during power-on, ignore them and do nothing, 127 // else reply with <Feature Abort>["Unrecognized Opcode"] 128 // <Deck Status>, <Tuner Device Status>, <Tuner Cleared Status>, <Timer Status> 129 addHandler(Constants.MESSAGE_RECORD_STATUS, mBystander); 130 131 // If TV supports the following messages during power-on, reply with <Feature Abort>["Not 132 // in correct mode to respond"], else reply with <Feature Abort>["Unrecognized Opcode"] 133 // <Give Tuner Device Status>, <Select Digital Service>, <Tuner Step Decrement>, 134 // <Tuner Stem Increment>, <Menu Status>. 135 addHandler(Constants.MESSAGE_RECORD_TV_SCREEN, mAborterIncorrectMode); 136 addHandler(Constants.MESSAGE_INITIATE_ARC, mAborterIncorrectMode); 137 addHandler(Constants.MESSAGE_TERMINATE_ARC, mAborterIncorrectMode); 138 139 addHandler(Constants.MESSAGE_GIVE_PHYSICAL_ADDRESS, mBypasser); 140 addHandler(Constants.MESSAGE_GET_MENU_LANGUAGE, mBypasser); 141 addHandler(Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS, mBypasser); 142 addHandler(Constants.MESSAGE_GIVE_DEVICE_VENDOR_ID, mBypasser); 143 addHandler(Constants.MESSAGE_GIVE_OSD_NAME, mBypasser); 144 addHandler(Constants.MESSAGE_SET_OSD_NAME, mBypasser); 145 146 addHandler(Constants.MESSAGE_USER_CONTROL_PRESSED, mUserControlProcessedHandler); 147 148 addHandler(Constants.MESSAGE_GIVE_DEVICE_POWER_STATUS, mBypasser); 149 addHandler(Constants.MESSAGE_ABORT, mBypasser); 150 addHandler(Constants.MESSAGE_GET_CEC_VERSION, mBypasser); 151 152 addHandler(Constants.MESSAGE_VENDOR_COMMAND_WITH_ID, mAborterIncorrectMode); 153 addHandler(Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE, mAborterIncorrectMode); 154 } 155 156 private void addHandler(int opcode, CecMessageHandler handler) { 157 mCecMessageHandlers.put(opcode, handler); 158 } 159 160 /** 161 * Handles the CEC message in the standby mode. 162 * 163 * @param message {@link HdmiCecMessage} to be processed 164 * @return true if the message is handled in the handler, false means that the message is need 165 * to be dispatched to the local device. 166 */ 167 boolean handleCommand(HdmiCecMessage message) { 168 CecMessageHandler handler = mCecMessageHandlers.get(message.getOpcode()); 169 if (handler != null) { 170 return handler.handle(message); 171 } 172 return mDefaultHandler.handle(message); 173 } 174} 175