13dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang/*
23dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang * Copyright (C) 2014 The Android Open Source Project
33dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang *
43dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang * Licensed under the Apache License, Version 2.0 (the "License");
53dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang * you may not use this file except in compliance with the License.
63dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang * You may obtain a copy of the License at
73dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang *
83dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang *      http://www.apache.org/licenses/LICENSE-2.0
93dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang *
103dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang * Unless required by applicable law or agreed to in writing, software
113dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang * distributed under the License is distributed on an "AS IS" BASIS,
123dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang * See the License for the specific language governing permissions and
143dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang * limitations under the License.
153dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang */
163dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang
173dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jangpackage com.android.server.hdmi;
183dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang
1912e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jangimport static android.hardware.hdmi.HdmiControlManager.ONE_TOUCH_RECORD_CHECK_RECORDER_CONNECTION;
2012e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jangimport static android.hardware.hdmi.HdmiControlManager.ONE_TOUCH_RECORD_RECORDING_ANALOGUE_SERVICE;
2112e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jangimport static android.hardware.hdmi.HdmiControlManager.ONE_TOUCH_RECORD_RECORDING_CURRENTLY_SELECTED_SOURCE;
2212e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jangimport static android.hardware.hdmi.HdmiControlManager.ONE_TOUCH_RECORD_RECORDING_DIGITAL_SERVICE;
2312e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jangimport static android.hardware.hdmi.HdmiControlManager.ONE_TOUCH_RECORD_RECORDING_EXTERNAL_INPUT;
24b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang
25b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jangimport android.util.Slog;
26b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang
27b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jangimport com.android.server.hdmi.HdmiControlService.SendMessageCallback;
28a6b2a7a59ab79b2d91412c1095d1c49b8dc9d507Jungshik Jang
293dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang/**
3012e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang * Feature action that performs one touch record.
313dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang */
32b509c2ecd99619248b7a07fb0fa978bb27f25cc3Jungshik Jangpublic class OneTouchRecordAction extends HdmiCecFeatureAction {
33b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    private static final String TAG = "OneTouchRecordAction";
34b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang
3512e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    // Timer out for waiting <Record Status> 120s
3612e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang    private static final int RECORD_STATUS_TIMEOUT_MS = 120000;
37b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang
38b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    // State that waits for <Record Status> once sending <Record On>
39b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    private static final int STATE_WAITING_FOR_RECORD_STATUS = 1;
40b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    // State that describes recording in progress.
41b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    private static final int STATE_RECORDING_IN_PROGRESS = 2;
42b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang
433dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang    private final int mRecorderAddress;
44b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    private final byte[] mRecordSource;
453dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang
46b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    OneTouchRecordAction(HdmiCecLocalDevice source, int recorderAddress, byte[] recordSource) {
473dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang        super(source);
483dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang        mRecorderAddress = recorderAddress;
49b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang        mRecordSource = recordSource;
503dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang    }
513dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang
523dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang    @Override
533dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang    boolean start() {
54b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang        sendRecordOn();
55b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang        return true;
563dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang    }
573dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang
58b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    private void sendRecordOn() {
59b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang        sendCommand(HdmiCecMessageBuilder.buildRecordOn(getSourceAddress(), mRecorderAddress,
60b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang                mRecordSource),
61b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang                new SendMessageCallback() {
62b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang                @Override
63b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang                    public void onSendCompleted(int error) {
64b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang                        // if failed to send <Record On>, display error message and finish action.
65b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang                        if (error != Constants.SEND_RESULT_SUCCESS) {
6612e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang                            tv().announceOneTouchRecordResult(
67326aef0c9402742e29c4503c857f93e75cf9a6ecJungshik Jang                                    mRecorderAddress,
6812e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang                                    ONE_TOUCH_RECORD_CHECK_RECORDER_CONNECTION);
69b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang                            finish();
70b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang                            return;
71b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang                        }
72b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang                    }
73b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang                });
745352081c662299b618335bf3024058fa04ef2dfdJungshik Jang        mState = STATE_WAITING_FOR_RECORD_STATUS;
755352081c662299b618335bf3024058fa04ef2dfdJungshik Jang        addTimer(mState, RECORD_STATUS_TIMEOUT_MS);
76a6b2a7a59ab79b2d91412c1095d1c49b8dc9d507Jungshik Jang    }
77a6b2a7a59ab79b2d91412c1095d1c49b8dc9d507Jungshik Jang
783dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang    @Override
793dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang    boolean processCommand(HdmiCecMessage cmd) {
805352081c662299b618335bf3024058fa04ef2dfdJungshik Jang        if (mState != STATE_WAITING_FOR_RECORD_STATUS || mRecorderAddress != cmd.getSource()) {
81b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang            return false;
82b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang        }
83b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang
84b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang        switch (cmd.getOpcode()) {
85b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang            case Constants.MESSAGE_RECORD_STATUS:
86b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang                return handleRecordStatus(cmd);
87b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang        }
883dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang        return false;
893dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang    }
903dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang
91b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    private boolean handleRecordStatus(HdmiCecMessage cmd) {
92b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang        // Only handle message coming from original recorder.
93b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang        if (cmd.getSource() != mRecorderAddress) {
94b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang            return false;
95b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang        }
96b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang
97b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang        int recordStatus = cmd.getParams()[0];
98326aef0c9402742e29c4503c857f93e75cf9a6ecJungshik Jang        tv().announceOneTouchRecordResult(mRecorderAddress, recordStatus);
99b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang        Slog.i(TAG, "Got record status:" + recordStatus + " from " + cmd.getSource());
100b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang
101b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang        // If recording started successfully, change state and keep this action until <Record Off>
102b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang        // received. Otherwise, finish action.
10312e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang        switch (recordStatus) {
10412e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang            case ONE_TOUCH_RECORD_RECORDING_CURRENTLY_SELECTED_SOURCE:
10512e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang            case ONE_TOUCH_RECORD_RECORDING_DIGITAL_SERVICE:
10612e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang            case ONE_TOUCH_RECORD_RECORDING_ANALOGUE_SERVICE:
10712e5dcefe136b58562f39604e6a8460ac92cb895Jungshik Jang            case ONE_TOUCH_RECORD_RECORDING_EXTERNAL_INPUT:
108b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang                mState = STATE_RECORDING_IN_PROGRESS;
109b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang                mActionTimer.clearTimerMessage();
110b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang                break;
111b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang            default:
112b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang                finish();
113b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang                break;
114b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang        }
115b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang        return true;
116b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang    }
117b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang
1183dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang    @Override
1193dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang    void handleTimerEvent(int state) {
120b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang        if (mState != state) {
121b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang            Slog.w(TAG, "Timeout in invalid state:[Expected:" + mState + ", Actual:" + state + "]");
122b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang            return;
123b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang        }
124b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang
125326aef0c9402742e29c4503c857f93e75cf9a6ecJungshik Jang        tv().announceOneTouchRecordResult(mRecorderAddress,
126326aef0c9402742e29c4503c857f93e75cf9a6ecJungshik Jang                ONE_TOUCH_RECORD_CHECK_RECORDER_CONNECTION);
127b6591b8e5399099dc6b7693e0fc719b613aba89cJungshik Jang        finish();
1283dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang    }
1293dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang
1303dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang    int getRecorderAddress() {
1313dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang        return mRecorderAddress;
1323dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang    }
1333dcdd71e203f7751155ec83468e0f8092e8ea80bJungshik Jang}
134