blob: 9b4950b5b1bacb91b51179d77e14b4a9c1c0f00b [file] [log] [blame]
Jungshik Jang67ea5212014-05-15 14:05:24 +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
Jungshik Jang61f4fbd2014-08-06 19:21:12 +090019import android.hardware.hdmi.HdmiDeviceInfo;
Jungshik Jang67ea5212014-05-15 14:05:24 +090020import android.util.Slog;
21
22/**
23 * Feature action that handles enabling/disabling of ARC transmission channel.
24 * Once TV gets <Initiate ARC>, TV sends <Report ARC Initiated> to AV Receiver.
25 * If it fails or it gets <Terminate ARC>, TV just disables ARC.
26 */
Jungshik Jangb509c2e2014-08-07 13:45:01 +090027final class SetArcTransmissionStateAction extends HdmiCecFeatureAction {
Jungshik Jang67ea5212014-05-15 14:05:24 +090028 private static final String TAG = "SetArcTransmissionStateAction";
29
30 // State in which the action sent <Rerpot Arc Initiated> and
31 // is waiting for time out. If it receives <Feature Abort> within timeout
32 // ARC should be disabled.
33 private static final int STATE_WAITING_TIMEOUT = 1;
34
35 private final boolean mEnabled;
36 private final int mAvrAddress;
37
38 /**
39 * @Constructor
40 *
Jungshik Jang79c58a42014-06-16 16:45:36 +090041 * @param source {@link HdmiCecLocalDevice} instance
Jungshik Jang67ea5212014-05-15 14:05:24 +090042 * @param enabled whether to enable ARC Transmission channel
43 */
Jungshik Jang79c58a42014-06-16 16:45:36 +090044 SetArcTransmissionStateAction(HdmiCecLocalDevice source, int avrAddress,
Jungshik Jang67ea5212014-05-15 14:05:24 +090045 boolean enabled) {
Jungshik Jang79c58a42014-06-16 16:45:36 +090046 super(source);
Jungshik Jang61f4fbd2014-08-06 19:21:12 +090047 HdmiUtils.verifyAddressType(getSourceAddress(), HdmiDeviceInfo.DEVICE_TV);
48 HdmiUtils.verifyAddressType(avrAddress, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
Jungshik Jang67ea5212014-05-15 14:05:24 +090049 mAvrAddress = avrAddress;
50 mEnabled = enabled;
51 }
52
Jungshik Jang67ea5212014-05-15 14:05:24 +090053 @Override
54 boolean start() {
Jinsuk Kim71651d32015-03-27 08:21:15 +090055 // Seq #37.
Jungshik Jang67ea5212014-05-15 14:05:24 +090056 if (mEnabled) {
Jinsuk Kim08783972015-04-16 07:46:18 +090057 // Enable ARC status immediately before sending <Report Arc Initiated>.
Jungshik Jang2e8f1b62014-09-03 08:28:02 +090058 // If AVR responds with <Feature Abort>, disable ARC status again.
59 // This is different from spec that says that turns ARC status to
60 // "Enabled" if <Report ARC Initiated> is acknowledged and no
61 // <Feature Abort> is received.
62 // But implemented this way to save the time having to wait for
63 // <Feature Abort>.
64 setArcStatus(true);
65 // If succeeds to send <Report ARC Initiated>, wait general timeout
66 // to check whether there is no <Feature Abort> for <Report ARC Initiated>.
67 mState = STATE_WAITING_TIMEOUT;
68 addTimer(mState, HdmiConfig.TIMEOUT_MS);
Jungshik Jangd643f762014-05-22 19:28:09 +090069 sendReportArcInitiated();
Jungshik Jang67ea5212014-05-15 14:05:24 +090070 } else {
71 setArcStatus(false);
72 finish();
73 }
74 return true;
75 }
76
Jungshik Jangd643f762014-05-22 19:28:09 +090077 private void sendReportArcInitiated() {
78 HdmiCecMessage command =
Jungshik Jang79c58a42014-06-16 16:45:36 +090079 HdmiCecMessageBuilder.buildReportArcInitiated(getSourceAddress(), mAvrAddress);
Jungshik Jangd643f762014-05-22 19:28:09 +090080 sendCommand(command, new HdmiControlService.SendMessageCallback() {
81 @Override
82 public void onSendCompleted(int error) {
Jinsuk Kim08783972015-04-16 07:46:18 +090083 switch (error) {
84 case Constants.SEND_RESULT_SUCCESS:
85 case Constants.SEND_RESULT_BUSY:
86 case Constants.SEND_RESULT_FAILURE:
87 // The result of the command transmission, unless it is an obvious
88 // failure indicated by the target device (or lack thereof), should
89 // not affect the ARC status. Ignores it silently.
90 break;
91 case Constants.SEND_RESULT_NAK:
92 // If <Report ARC Initiated> is negatively ack'ed, disable ARC and
93 // send <Report ARC Terminated> directly.
94 setArcStatus(false);
95 HdmiLogger.debug("Failed to send <Report Arc Initiated>.");
96 finish();
97 break;
Jungshik Jangd643f762014-05-22 19:28:09 +090098 }
99 }
100 });
101 }
102
Jungshik Jang67ea5212014-05-15 14:05:24 +0900103 private void setArcStatus(boolean enabled) {
Jungshik Jang79c58a42014-06-16 16:45:36 +0900104 boolean wasEnabled = tv().setArcStatus(enabled);
Jungshik Jangc94ac5c2014-08-27 13:48:37 +0900105 Slog.i(TAG, "Change arc status [old:" + wasEnabled + ", new:" + enabled + "]");
Jungshik Jang67ea5212014-05-15 14:05:24 +0900106
107 // If enabled before and set to "disabled" and send <Report Arc Terminated> to
108 // av reciever.
109 if (!enabled && wasEnabled) {
Jungshik Jang79c58a42014-06-16 16:45:36 +0900110 sendCommand(HdmiCecMessageBuilder.buildReportArcTerminated(getSourceAddress(),
111 mAvrAddress));
Jungshik Jang67ea5212014-05-15 14:05:24 +0900112 }
113 }
114
115 @Override
116 boolean processCommand(HdmiCecMessage cmd) {
117 if (mState != STATE_WAITING_TIMEOUT) {
118 return false;
119 }
120
121 int opcode = cmd.getOpcode();
Jinsuk Kimc0c20d02014-07-04 14:34:31 +0900122 if (opcode == Constants.MESSAGE_FEATURE_ABORT) {
Jungshik Jang339227d2014-08-25 15:37:20 +0900123 int originalOpcode = cmd.getParams()[0] & 0xFF;
124 if (originalOpcode == Constants.MESSAGE_REPORT_ARC_INITIATED) {
Jungshik Jang2e8f1b62014-09-03 08:28:02 +0900125 HdmiLogger.debug("Feature aborted for <Report Arc Initiated>");
Jungshik Jang339227d2014-08-25 15:37:20 +0900126 setArcStatus(false);
127 finish();
128 return true;
129 }
Jungshik Jang67ea5212014-05-15 14:05:24 +0900130 }
Jungshik Jang339227d2014-08-25 15:37:20 +0900131 return false;
Jungshik Jang67ea5212014-05-15 14:05:24 +0900132 }
133
134 @Override
135 void handleTimerEvent(int state) {
136 if (mState != state || mState != STATE_WAITING_TIMEOUT) {
137 return;
138 }
139 // Expire timeout for <Feature Abort>.
140 finish();
141 }
142}