167ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang/* 267ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * Copyright (C) 2014 The Android Open Source Project 367ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * 467ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * Licensed under the Apache License, Version 2.0 (the "License"); 567ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * you may not use this file except in compliance with the License. 667ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * You may obtain a copy of the License at 767ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * 867ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * http://www.apache.org/licenses/LICENSE-2.0 967ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * 1067ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * Unless required by applicable law or agreed to in writing, software 1167ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * distributed under the License is distributed on an "AS IS" BASIS, 1267ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1367ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * See the License for the specific language governing permissions and 1467ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * limitations under the License. 1567ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang */ 1667ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 1767ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jangpackage com.android.server.hdmi; 1867ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 1961f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jangimport android.hardware.hdmi.HdmiDeviceInfo; 20bc6e372b25d7d62efecefba09304c5a66218c91aDonghyun Choimport android.hardware.tv.cec.V1_0.SendMessageResult; 2167ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jangimport android.util.Slog; 2267ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 2367ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang/** 2467ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * Feature action that handles enabling/disabling of ARC transmission channel. 2567ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * Once TV gets <Initiate ARC>, TV sends <Report ARC Initiated> to AV Receiver. 2667ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * If it fails or it gets <Terminate ARC>, TV just disables ARC. 2767ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang */ 28b509c2ecd99619248b7a07fb0fa978bb27f25cc3Jungshik Jangfinal class SetArcTransmissionStateAction extends HdmiCecFeatureAction { 2967ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang private static final String TAG = "SetArcTransmissionStateAction"; 3067ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 3167ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang // State in which the action sent <Rerpot Arc Initiated> and 3267ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang // is waiting for time out. If it receives <Feature Abort> within timeout 3367ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang // ARC should be disabled. 3467ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang private static final int STATE_WAITING_TIMEOUT = 1; 3567ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 3667ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang private final boolean mEnabled; 3767ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang private final int mAvrAddress; 3867ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 3967ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang /** 4067ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * @Constructor 4167ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * 4279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * @param source {@link HdmiCecLocalDevice} instance 4367ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * @param enabled whether to enable ARC Transmission channel 4467ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang */ 4579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang SetArcTransmissionStateAction(HdmiCecLocalDevice source, int avrAddress, 4667ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang boolean enabled) { 4779c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang super(source); 4861f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang HdmiUtils.verifyAddressType(getSourceAddress(), HdmiDeviceInfo.DEVICE_TV); 4961f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang HdmiUtils.verifyAddressType(avrAddress, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); 5067ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang mAvrAddress = avrAddress; 5167ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang mEnabled = enabled; 5267ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 5367ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 5467ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang @Override 5567ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang boolean start() { 5671651d37125a5fe7339fb5f140876c891a8275dfJinsuk Kim // Seq #37. 5767ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang if (mEnabled) { 58087839755d311b09f40a1b9db1d09c9c8bdf9872Jinsuk Kim // Enable ARC status immediately before sending <Report Arc Initiated>. 592e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang // If AVR responds with <Feature Abort>, disable ARC status again. 602e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang // This is different from spec that says that turns ARC status to 612e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang // "Enabled" if <Report ARC Initiated> is acknowledged and no 622e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang // <Feature Abort> is received. 632e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang // But implemented this way to save the time having to wait for 642e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang // <Feature Abort>. 652e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang setArcStatus(true); 662e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang // If succeeds to send <Report ARC Initiated>, wait general timeout 672e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang // to check whether there is no <Feature Abort> for <Report ARC Initiated>. 682e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang mState = STATE_WAITING_TIMEOUT; 692e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang addTimer(mState, HdmiConfig.TIMEOUT_MS); 70d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang sendReportArcInitiated(); 7167ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } else { 7267ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang setArcStatus(false); 7367ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang finish(); 7467ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 7567ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang return true; 7667ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 7767ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 78d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang private void sendReportArcInitiated() { 79d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang HdmiCecMessage command = 8079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang HdmiCecMessageBuilder.buildReportArcInitiated(getSourceAddress(), mAvrAddress); 81d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang sendCommand(command, new HdmiControlService.SendMessageCallback() { 82d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang @Override 83d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang public void onSendCompleted(int error) { 84087839755d311b09f40a1b9db1d09c9c8bdf9872Jinsuk Kim switch (error) { 85bc6e372b25d7d62efecefba09304c5a66218c91aDonghyun Cho case SendMessageResult.SUCCESS: 86bc6e372b25d7d62efecefba09304c5a66218c91aDonghyun Cho case SendMessageResult.BUSY: 87bc6e372b25d7d62efecefba09304c5a66218c91aDonghyun Cho case SendMessageResult.FAIL: 88087839755d311b09f40a1b9db1d09c9c8bdf9872Jinsuk Kim // The result of the command transmission, unless it is an obvious 89087839755d311b09f40a1b9db1d09c9c8bdf9872Jinsuk Kim // failure indicated by the target device (or lack thereof), should 90087839755d311b09f40a1b9db1d09c9c8bdf9872Jinsuk Kim // not affect the ARC status. Ignores it silently. 91087839755d311b09f40a1b9db1d09c9c8bdf9872Jinsuk Kim break; 92bc6e372b25d7d62efecefba09304c5a66218c91aDonghyun Cho case SendMessageResult.NACK: 93087839755d311b09f40a1b9db1d09c9c8bdf9872Jinsuk Kim // If <Report ARC Initiated> is negatively ack'ed, disable ARC and 94087839755d311b09f40a1b9db1d09c9c8bdf9872Jinsuk Kim // send <Report ARC Terminated> directly. 95087839755d311b09f40a1b9db1d09c9c8bdf9872Jinsuk Kim setArcStatus(false); 96087839755d311b09f40a1b9db1d09c9c8bdf9872Jinsuk Kim HdmiLogger.debug("Failed to send <Report Arc Initiated>."); 97087839755d311b09f40a1b9db1d09c9c8bdf9872Jinsuk Kim finish(); 98087839755d311b09f40a1b9db1d09c9c8bdf9872Jinsuk Kim break; 99d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang } 100d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang } 101d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang }); 102d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang } 103d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang 10467ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang private void setArcStatus(boolean enabled) { 10579c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang boolean wasEnabled = tv().setArcStatus(enabled); 106c94ac5cffc982898bc4f7a5d97d8fad5520ff444Jungshik Jang Slog.i(TAG, "Change arc status [old:" + wasEnabled + ", new:" + enabled + "]"); 10767ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 10867ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang // If enabled before and set to "disabled" and send <Report Arc Terminated> to 10967ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang // av reciever. 11067ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang if (!enabled && wasEnabled) { 11179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang sendCommand(HdmiCecMessageBuilder.buildReportArcTerminated(getSourceAddress(), 11279c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mAvrAddress)); 11367ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 11467ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 11567ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 11667ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang @Override 11767ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang boolean processCommand(HdmiCecMessage cmd) { 11867ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang if (mState != STATE_WAITING_TIMEOUT) { 11967ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang return false; 12067ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 12167ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 12267ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang int opcode = cmd.getOpcode(); 123c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim if (opcode == Constants.MESSAGE_FEATURE_ABORT) { 124339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang int originalOpcode = cmd.getParams()[0] & 0xFF; 125339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang if (originalOpcode == Constants.MESSAGE_REPORT_ARC_INITIATED) { 1262e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang HdmiLogger.debug("Feature aborted for <Report Arc Initiated>"); 127339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang setArcStatus(false); 128339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang finish(); 129339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang return true; 130339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang } 13167ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 132339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang return false; 13367ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 13467ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 13567ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang @Override 13667ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang void handleTimerEvent(int state) { 13767ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang if (mState != state || mState != STATE_WAITING_TIMEOUT) { 13867ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang return; 13967ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 14067ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang // Expire timeout for <Feature Abort>. 14167ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang finish(); 14267ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 14367ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang} 144