blob: d200d359bffbb312ca70c63e5a8462c14c22447a [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) {
Jungshik Jang2e8f1b62014-09-03 08:28:02 +090057 // Enable ARC status immediately after sending <Report Arc Initiated>.
58 // 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) {
Jungshik Jang2e8f1b62014-09-03 08:28:02 +090083 if (error != Constants.SEND_RESULT_SUCCESS) {
Jungshik Jangd643f762014-05-22 19:28:09 +090084 // If fails to send <Report ARC Initiated>, disable ARC and
85 // send <Report ARC Terminated> directly.
Jungshik Jangd643f762014-05-22 19:28:09 +090086 setArcStatus(false);
Jungshik Jang2e8f1b62014-09-03 08:28:02 +090087 HdmiLogger.debug("Failed to send <Report Arc Initiated>.");
Jungshik Jangd643f762014-05-22 19:28:09 +090088 finish();
89 }
90 }
91 });
92 }
93
Jungshik Jang67ea5212014-05-15 14:05:24 +090094 private void setArcStatus(boolean enabled) {
Jungshik Jang79c58a42014-06-16 16:45:36 +090095 boolean wasEnabled = tv().setArcStatus(enabled);
Jungshik Jangc94ac5c2014-08-27 13:48:37 +090096 Slog.i(TAG, "Change arc status [old:" + wasEnabled + ", new:" + enabled + "]");
Jungshik Jang67ea5212014-05-15 14:05:24 +090097
98 // If enabled before and set to "disabled" and send <Report Arc Terminated> to
99 // av reciever.
100 if (!enabled && wasEnabled) {
Jungshik Jang79c58a42014-06-16 16:45:36 +0900101 sendCommand(HdmiCecMessageBuilder.buildReportArcTerminated(getSourceAddress(),
102 mAvrAddress));
Jungshik Jang67ea5212014-05-15 14:05:24 +0900103 }
104 }
105
106 @Override
107 boolean processCommand(HdmiCecMessage cmd) {
108 if (mState != STATE_WAITING_TIMEOUT) {
109 return false;
110 }
111
112 int opcode = cmd.getOpcode();
Jinsuk Kimc0c20d02014-07-04 14:34:31 +0900113 if (opcode == Constants.MESSAGE_FEATURE_ABORT) {
Jungshik Jang339227d2014-08-25 15:37:20 +0900114 int originalOpcode = cmd.getParams()[0] & 0xFF;
115 if (originalOpcode == Constants.MESSAGE_REPORT_ARC_INITIATED) {
Jungshik Jang2e8f1b62014-09-03 08:28:02 +0900116 HdmiLogger.debug("Feature aborted for <Report Arc Initiated>");
Jungshik Jang339227d2014-08-25 15:37:20 +0900117 setArcStatus(false);
118 finish();
119 return true;
120 }
Jungshik Jang67ea5212014-05-15 14:05:24 +0900121 }
Jungshik Jang339227d2014-08-25 15:37:20 +0900122 return false;
Jungshik Jang67ea5212014-05-15 14:05:24 +0900123 }
124
125 @Override
126 void handleTimerEvent(int state) {
127 if (mState != state || mState != STATE_WAITING_TIMEOUT) {
128 return;
129 }
130 // Expire timeout for <Feature Abort>.
131 finish();
132 }
133}