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() { 5567ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang if (mEnabled) { 562e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang // Enable ARC status immediately after sending <Report Arc Initiated>. 572e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang // If AVR responds with <Feature Abort>, disable ARC status again. 582e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang // This is different from spec that says that turns ARC status to 592e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang // "Enabled" if <Report ARC Initiated> is acknowledged and no 602e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang // <Feature Abort> is received. 612e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang // But implemented this way to save the time having to wait for 622e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang // <Feature Abort>. 632e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang setArcStatus(true); 642e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang // If succeeds to send <Report ARC Initiated>, wait general timeout 652e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang // to check whether there is no <Feature Abort> for <Report ARC Initiated>. 662e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang mState = STATE_WAITING_TIMEOUT; 672e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang addTimer(mState, HdmiConfig.TIMEOUT_MS); 68d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang sendReportArcInitiated(); 6967ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } else { 7067ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang setArcStatus(false); 7167ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang finish(); 7267ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 7367ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang return true; 7467ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 7567ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 76d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang private void sendReportArcInitiated() { 77d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang HdmiCecMessage command = 7879c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang HdmiCecMessageBuilder.buildReportArcInitiated(getSourceAddress(), mAvrAddress); 79d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang sendCommand(command, new HdmiControlService.SendMessageCallback() { 80d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang @Override 81d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang public void onSendCompleted(int error) { 822e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang if (error != Constants.SEND_RESULT_SUCCESS) { 83d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang // If fails to send <Report ARC Initiated>, disable ARC and 84d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang // send <Report ARC Terminated> directly. 85d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang setArcStatus(false); 862e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang HdmiLogger.debug("Failed to send <Report Arc Initiated>."); 87d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang finish(); 88d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang } 89d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang } 90d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang }); 91d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang } 92d643f764f72efc1e7aa67392bf9ac40720ae14c3Jungshik Jang 9367ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang private void setArcStatus(boolean enabled) { 9479c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang boolean wasEnabled = tv().setArcStatus(enabled); 95c94ac5cffc982898bc4f7a5d97d8fad5520ff444Jungshik Jang Slog.i(TAG, "Change arc status [old:" + wasEnabled + ", new:" + enabled + "]"); 9667ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 9767ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang // If enabled before and set to "disabled" and send <Report Arc Terminated> to 9867ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang // av reciever. 9967ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang if (!enabled && wasEnabled) { 10079c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang sendCommand(HdmiCecMessageBuilder.buildReportArcTerminated(getSourceAddress(), 10179c58a4b97f27ede6a1b680d2fece9c2a0edf7b7Jungshik Jang mAvrAddress)); 10267ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 10367ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 10467ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 10567ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang @Override 10667ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang boolean processCommand(HdmiCecMessage cmd) { 10767ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang if (mState != STATE_WAITING_TIMEOUT) { 10867ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang return false; 10967ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 11067ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 11167ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang int opcode = cmd.getOpcode(); 112c0c20d0522d7756d80f011e7a54bf3b51c78df41Jinsuk Kim if (opcode == Constants.MESSAGE_FEATURE_ABORT) { 113339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang int originalOpcode = cmd.getParams()[0] & 0xFF; 114339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang if (originalOpcode == Constants.MESSAGE_REPORT_ARC_INITIATED) { 1152e8f1b6399089626b4f0249427626ba6e63a62efJungshik Jang HdmiLogger.debug("Feature aborted for <Report Arc Initiated>"); 116339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang setArcStatus(false); 117339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang finish(); 118339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang return true; 119339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang } 12067ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 121339227da7cf025ce4ae0c85ddc52643d63972321Jungshik Jang return false; 12267ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 12367ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang 12467ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang @Override 12567ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang void handleTimerEvent(int state) { 12667ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang if (mState != state || mState != STATE_WAITING_TIMEOUT) { 12767ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang return; 12867ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 12967ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang // Expire timeout for <Feature Abort>. 13067ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang finish(); 13167ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang } 13267ea521d14f366fe5aac09e512865d31bfa0ee53Jungshik Jang} 133