blob: 8c404249cfd50514e0c1ace40ff6d03eb2e37ec4 [file] [log] [blame]
Yuncheol Heo25c20292014-07-31 17:59:39 +09001/*
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) {
Yuncheol Heo6aae6522014-08-05 14:48:37 +090051 mService.maySendFeatureAbortCommand(message, mReason);
Yuncheol Heo25c20292014-07-31 17:59:39 +090052 return true;
53 }
54 }
55
56 private final class AutoOnHandler implements CecMessageHandler {
57 @Override
58 public boolean handle(HdmiCecMessage message) {
59 if (!mTv.getAutoWakeup()) {
60 mAborterRefused.handle(message);
61 return true;
62 }
63 return false;
64 }
65 }
66
67 private final class UserControlProcessedHandler implements CecMessageHandler {
68 @Override
69 public boolean handle(HdmiCecMessage message) {
70 // The power status here is always standby.
71 if (HdmiCecLocalDevice.isPowerOnOrToggleCommand(message)) {
72 return false;
73 } else if (HdmiCecLocalDevice.isPowerOffOrToggleCommand(message)) {
74 return true;
75 }
76 return mAborterIncorrectMode.handle(message);
77 }
78 }
79
80 private final HdmiControlService mService;
81 private final HdmiCecLocalDeviceTv mTv;
82
83 private final SparseArray<CecMessageHandler> mCecMessageHandlers = new SparseArray<>();
84 private final CecMessageHandler mDefaultHandler = new Aborter(
85 Constants.ABORT_UNRECOGNIZED_OPCODE);
86 private final CecMessageHandler mAborterIncorrectMode = new Aborter(
87 Constants.ABORT_NOT_IN_CORRECT_MODE);
88 private final CecMessageHandler mAborterRefused = new Aborter(Constants.ABORT_REFUSED);
89 private final CecMessageHandler mAutoOnHandler = new AutoOnHandler();
90 private final CecMessageHandler mBypasser = new Bypasser();
91 private final CecMessageHandler mBystander = new Bystander();
92 private final UserControlProcessedHandler
93 mUserControlProcessedHandler = new UserControlProcessedHandler();
94
95 public HdmiCecStandbyModeHandler(HdmiControlService service, HdmiCecLocalDeviceTv tv) {
96 mService = service;
97 mTv = tv;
98
99 addHandler(Constants.MESSAGE_IMAGE_VIEW_ON, mAutoOnHandler);
100 addHandler(Constants.MESSAGE_TEXT_VIEW_ON, mAutoOnHandler);
101
102 addHandler(Constants.MESSAGE_ACTIVE_SOURCE, mBystander);
103 addHandler(Constants.MESSAGE_REQUEST_ACTIVE_SOURCE, mBystander);
104 addHandler(Constants.MESSAGE_ROUTING_CHANGE, mBystander);
105 addHandler(Constants.MESSAGE_ROUTING_INFORMATION, mBystander);
106 addHandler(Constants.MESSAGE_SET_STREAM_PATH, mBystander);
107 addHandler(Constants.MESSAGE_STANDBY, mBystander);
108 addHandler(Constants.MESSAGE_SET_MENU_LANGUAGE, mBystander);
109 addHandler(Constants.MESSAGE_DEVICE_VENDOR_ID, mBystander);
110 addHandler(Constants.MESSAGE_USER_CONTROL_RELEASED, mBystander);
111 addHandler(Constants.MESSAGE_REPORT_POWER_STATUS, mBystander);
112 addHandler(Constants.MESSAGE_FEATURE_ABORT, mBystander);
113 addHandler(Constants.MESSAGE_INACTIVE_SOURCE, mBystander);
114 addHandler(Constants.MESSAGE_SYSTEM_AUDIO_MODE_STATUS, mBystander);
115 addHandler(Constants.MESSAGE_REPORT_AUDIO_STATUS, mBystander);
116
117 // If TV supports the following messages during power-on, ignore them and do nothing,
118 // else reply with <Feature Abort>["Unrecognized Opcode"]
119 // <Deck Status>, <Tuner Device Status>, <Tuner Cleared Status>, <Timer Status>
120 addHandler(Constants.MESSAGE_RECORD_STATUS, mBystander);
121
122 // If TV supports the following messages during power-on, reply with <Feature Abort>["Not
123 // in correct mode to respond"], else reply with <Feature Abort>["Unrecognized Opcode"]
124 // <Give Tuner Device Status>, <Select Digital Service>, <Tuner Step Decrement>,
125 // <Tuner Stem Increment>, <Menu Status>.
126 addHandler(Constants.MESSAGE_RECORD_TV_SCREEN, mAborterIncorrectMode);
127 addHandler(Constants.MESSAGE_INITIATE_ARC, mAborterIncorrectMode);
128 addHandler(Constants.MESSAGE_TERMINATE_ARC, mAborterIncorrectMode);
129
130 addHandler(Constants.MESSAGE_GIVE_PHYSICAL_ADDRESS, mBypasser);
131 addHandler(Constants.MESSAGE_GET_MENU_LANGUAGE, mBypasser);
132 addHandler(Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS, mBypasser);
133 addHandler(Constants.MESSAGE_GIVE_DEVICE_VENDOR_ID, mBypasser);
134 addHandler(Constants.MESSAGE_GIVE_OSD_NAME, mBypasser);
135 addHandler(Constants.MESSAGE_SET_OSD_NAME, mBypasser);
136
137 addHandler(Constants.MESSAGE_USER_CONTROL_PRESSED, mUserControlProcessedHandler);
138
139 addHandler(Constants.MESSAGE_GIVE_DEVICE_POWER_STATUS, mBypasser);
140 addHandler(Constants.MESSAGE_ABORT, mBypasser);
141 addHandler(Constants.MESSAGE_GET_CEC_VERSION, mBypasser);
142
143 addHandler(Constants.MESSAGE_VENDOR_COMMAND_WITH_ID, mAborterIncorrectMode);
144 addHandler(Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE, mAborterIncorrectMode);
145 }
146
147 private void addHandler(int opcode, CecMessageHandler handler) {
148 mCecMessageHandlers.put(opcode, handler);
149 }
150
151 /**
152 * Handles the CEC message in the standby mode.
153 *
154 * @param message {@link HdmiCecMessage} to be processed
155 * @return true if the message is handled in the handler, false means that the message is need
156 * to be dispatched to the local device.
157 */
158 boolean handleCommand(HdmiCecMessage message) {
159 CecMessageHandler handler = mCecMessageHandlers.get(message.getOpcode());
160 if (handler != null) {
161 return handler.handle(message);
162 }
163 return mDefaultHandler.handle(message);
164 }
165}