1package com.android.server.hdmi;
2
3/*
4 * Copyright (C) 2014 The Android Open Source Project
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 *      http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19import android.hardware.hdmi.HdmiControlManager;
20import android.hardware.hdmi.HdmiPlaybackClient;
21import android.hardware.hdmi.HdmiPlaybackClient.DisplayStatusCallback;
22import android.hardware.hdmi.IHdmiControlCallback;
23import android.os.RemoteException;
24import android.util.Slog;
25
26/**
27 * Feature action that queries the power status of other device. This action is initiated via
28 * {@link HdmiPlaybackClient#queryDisplayStatus(DisplayStatusCallback)} from the Android system
29 * working as playback device to get the power status of TV device.
30 * <p>
31 * Package-private, accessed by {@link HdmiControlService} only.
32 */
33final class DevicePowerStatusAction extends HdmiCecFeatureAction {
34    private static final String TAG = "DevicePowerStatusAction";
35
36    // State in which the action is waiting for <Report Power Status>.
37    private static final int STATE_WAITING_FOR_REPORT_POWER_STATUS = 1;
38
39    private final int mTargetAddress;
40    private final IHdmiControlCallback mCallback;
41
42    static DevicePowerStatusAction create(HdmiCecLocalDevice source,
43            int targetAddress, IHdmiControlCallback callback) {
44        if (source == null || callback == null) {
45            Slog.e(TAG, "Wrong arguments");
46            return null;
47        }
48        return new DevicePowerStatusAction(source, targetAddress, callback);
49    }
50
51    private DevicePowerStatusAction(HdmiCecLocalDevice localDevice,
52            int targetAddress, IHdmiControlCallback callback) {
53        super(localDevice);
54        mTargetAddress = targetAddress;
55        mCallback = callback;
56    }
57
58    @Override
59    boolean start() {
60        queryDevicePowerStatus();
61        mState = STATE_WAITING_FOR_REPORT_POWER_STATUS;
62        addTimer(mState, HdmiConfig.TIMEOUT_MS);
63        return true;
64    }
65
66    private void queryDevicePowerStatus() {
67        sendCommand(HdmiCecMessageBuilder.buildGiveDevicePowerStatus(getSourceAddress(),
68                mTargetAddress));
69    }
70
71    @Override
72    boolean processCommand(HdmiCecMessage cmd) {
73        if (mState != STATE_WAITING_FOR_REPORT_POWER_STATUS
74               || mTargetAddress != cmd.getSource()) {
75            return false;
76        }
77        if (cmd.getOpcode() == Constants.MESSAGE_REPORT_POWER_STATUS) {
78            int status = cmd.getParams()[0];
79            invokeCallback(status);
80            finish();
81            return true;
82        }
83        return false;
84    }
85
86    @Override
87    void handleTimerEvent(int state) {
88        if (mState != state) {
89            return;
90        }
91        if (state == STATE_WAITING_FOR_REPORT_POWER_STATUS) {
92            // Got no response from TV. Report status 'unknown'.
93            invokeCallback(HdmiControlManager.POWER_STATUS_UNKNOWN);
94            finish();
95        }
96    }
97
98    private void invokeCallback(int result) {
99        try {
100            mCallback.onComplete(result);
101        } catch (RemoteException e) {
102            Slog.e(TAG, "Callback failed:" + e);
103        }
104    }
105}
106