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; 2067ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jangimport android.util.Slog; 2167ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 2267ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang/** 2367ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * Feature action that handles enabling/disabling of ARC transmission channel. 2467ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * Once TV gets <Initiate ARC>, TV sends <Report ARC Initiated> to AV Receiver. 2567ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * If it fails or it gets <Terminate ARC>, TV just disables ARC. 2667ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang */ 27b509c2ecd99619248b7a07fb0fa978bb27f25cc3Jungshik Jangfinal class SetArcTransmissionStateAction extends HdmiCecFeatureAction { 2867ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang private static final String TAG = "SetArcTransmissionStateAction"; 2967ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 3067ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang // State in which the action sent <Rerpot Arc Initiated> and 3167ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang // is waiting for time out. If it receives <Feature Abort> within timeout 3267ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang // ARC should be disabled. 3367ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang private static final int STATE_WAITING_TIMEOUT = 1; 3467ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 3567ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang private final boolean mEnabled; 3667ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang private final int mAvrAddress; 3767ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 3867ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang /** 3967ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * @Constructor 4067ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * 4179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang * @param source {@link HdmiCecLocalDevice} instance 4267ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang * @param enabled whether to enable ARC Transmission channel 4367ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang */ 4479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang SetArcTransmissionStateAction(HdmiCecLocalDevice source, int avrAddress, 4567ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang boolean enabled) { 4679c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang super(source); 4761f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang HdmiUtils.verifyAddressType(getSourceAddress(), HdmiDeviceInfo.DEVICE_TV); 4861f4fbd2e8436a1ecd478c2a1f516d064a24d43bJungshik Jang HdmiUtils.verifyAddressType(avrAddress, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); 4967ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang mAvrAddress = avrAddress; 5067ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang mEnabled = enabled; 5167ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 5267ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 5367ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang @Override 5467ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang boolean start() { 5571651d37125a5fe7339fb5f140876c891a8275dfJinsuk Kim // Seq #37. 5667ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang if (mEnabled) { 57087839755d311b09f40a1b9db1d09c9c8bdf9872Jinsuk Kim // Enable ARC status immediately before sending <Report Arc Initiated>. 582e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang // If AVR responds with <Feature Abort>, disable ARC status again. 592e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang // This is different from spec that says that turns ARC status to 602e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang // "Enabled" if <Report ARC Initiated> is acknowledged and no 612e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang // <Feature Abort> is received. 622e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang // But implemented this way to save the time having to wait for 632e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang // <Feature Abort>. 642e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang setArcStatus(true); 652e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang // If succeeds to send <Report ARC Initiated>, wait general timeout 662e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang // to check whether there is no <Feature Abort> for <Report ARC Initiated>. 672e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang mState = STATE_WAITING_TIMEOUT; 682e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang addTimer(mState, HdmiConfig.TIMEOUT_MS); 69d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang sendReportArcInitiated(); 7067ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } else { 7167ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang setArcStatus(false); 7267ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang finish(); 7367ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 7467ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang return true; 7567ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 7667ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 77d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang private void sendReportArcInitiated() { 78d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang HdmiCecMessage command = 7979c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang HdmiCecMessageBuilder.buildReportArcInitiated(getSourceAddress(), mAvrAddress); 80d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang sendCommand(command, new HdmiControlService.SendMessageCallback() { 81d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang @Override 82d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang public void onSendCompleted(int error) { 83087839755d311b09f40a1b9db1d09c9c8bdf9872Jinsuk Kim switch (error) { 84087839755d311b09f40a1b9db1d09c9c8bdf9872Jinsuk Kim case Constants.SEND_RESULT_SUCCESS: 85087839755d311b09f40a1b9db1d09c9c8bdf9872Jinsuk Kim case Constants.SEND_RESULT_BUSY: 86087839755d311b09f40a1b9db1d09c9c8bdf9872Jinsuk Kim case Constants.SEND_RESULT_FAILURE: 87087839755d311b09f40a1b9db1d09c9c8bdf9872Jinsuk Kim // The result of the command transmission, unless it is an obvious 88087839755d311b09f40a1b9db1d09c9c8bdf9872Jinsuk Kim // failure indicated by the target device (or lack thereof), should 89087839755d311b09f40a1b9db1d09c9c8bdf9872Jinsuk Kim // not affect the ARC status. Ignores it silently. 90087839755d311b09f40a1b9db1d09c9c8bdf9872Jinsuk Kim break; 91087839755d311b09f40a1b9db1d09c9c8bdf9872Jinsuk Kim case Constants.SEND_RESULT_NAK: 92087839755d311b09f40a1b9db1d09c9c8bdf9872Jinsuk Kim // If <Report ARC Initiated> is negatively ack'ed, disable ARC and 93087839755d311b09f40a1b9db1d09c9c8bdf9872Jinsuk Kim // send <Report ARC Terminated> directly. 94087839755d311b09f40a1b9db1d09c9c8bdf9872Jinsuk Kim setArcStatus(false); 95087839755d311b09f40a1b9db1d09c9c8bdf9872Jinsuk Kim HdmiLogger.debug("Failed to send <Report Arc Initiated>."); 96087839755d311b09f40a1b9db1d09c9c8bdf9872Jinsuk Kim finish(); 97087839755d311b09f40a1b9db1d09c9c8bdf9872Jinsuk Kim break; 98d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang } 99d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang } 100d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang }); 101d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang } 102d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang 10367ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang private void setArcStatus(boolean enabled) { 10479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang boolean wasEnabled = tv().setArcStatus(enabled); 105c94ac5cffc982898bc4f7a5d97d8fad5520ff444Jungshik Jang Slog.i(TAG, "Change arc status [old:" + wasEnabled + ", new:" + enabled + "]"); 10667ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 10767ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang // If enabled before and set to "disabled" and send <Report Arc Terminated> to 10867ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang // av reciever. 10967ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang if (!enabled && wasEnabled) { 11079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang sendCommand(HdmiCecMessageBuilder.buildReportArcTerminated(getSourceAddress(), 11179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mAvrAddress)); 11267ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 11367ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 11467ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 11567ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang @Override 11667ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang boolean processCommand(HdmiCecMessage cmd) { 11767ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang if (mState != STATE_WAITING_TIMEOUT) { 11867ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang return false; 11967ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 12067ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 12167ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang int opcode = cmd.getOpcode(); 122c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim if (opcode == Constants.MESSAGE_FEATURE_ABORT) { 123339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang int originalOpcode = cmd.getParams()[0] & 0xFF; 124339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang if (originalOpcode == Constants.MESSAGE_REPORT_ARC_INITIATED) { 1252e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang HdmiLogger.debug("Feature aborted for <Report Arc Initiated>"); 126339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang setArcStatus(false); 127339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang finish(); 128339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang return true; 129339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang } 13067ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 131339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang return false; 13267ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 13367ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 13467ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang @Override 13567ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang void handleTimerEvent(int state) { 13667ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang if (mState != state || mState != STATE_WAITING_TIMEOUT) { 13767ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang return; 13867ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 13967ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang // Expire timeout for <Feature Abort>. 14067ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang finish(); 14167ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 14267ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang} 143