HdmiCecLocalDeviceTv.java revision a6ce7708d6124224399241503fadcafe0c4684d4
1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.hdmi;
18
19import android.hardware.hdmi.IHdmiControlCallback;
20import android.hardware.hdmi.HdmiCec;
21import android.hardware.hdmi.HdmiCecDeviceInfo;
22import android.hardware.hdmi.HdmiCecMessage;
23import android.os.RemoteException;
24import android.util.Slog;
25
26import java.util.Locale;
27
28/**
29 * Represent a logical device of type TV residing in Android system.
30 */
31final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
32    private static final String TAG = "HdmiCecLocalDeviceTv";
33
34    HdmiCecLocalDeviceTv(HdmiControlService service) {
35        super(service, HdmiCec.DEVICE_TV);
36    }
37
38    @Override
39    protected void onAddressAllocated(int logicalAddress) {
40        // TODO: vendor-specific initialization here.
41
42        mService.sendCecCommand(HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
43                mAddress, mService.getPhysicalAddress(), mDeviceType));
44        mService.sendCecCommand(HdmiCecMessageBuilder.buildDeviceVendorIdCommand(
45                mAddress, mService.getVendorId()));
46
47        mService.launchDeviceDiscovery(mAddress);
48        // TODO: Start routing control action, device discovery action.
49    }
50
51    @Override
52    protected boolean onMessage(HdmiCecMessage message) {
53        switch (message.getOpcode()) {
54            case HdmiCec.MESSAGE_REPORT_PHYSICAL_ADDRESS:
55                return handleReportPhysicalAddress(message);
56            default:
57                return super.onMessage(message);
58        }
59    }
60
61    /**
62     * Performs the action 'device select', or 'one touch play' initiated by TV.
63     *
64     * @param targetAddress logical address of the device to select
65     * @param callback callback object to report the result with
66     */
67    void deviceSelect(int targetAddress, IHdmiControlCallback callback) {
68        HdmiCecDeviceInfo targetDevice = mService.getDeviceInfo(targetAddress);
69        if (targetDevice == null) {
70            invokeCallback(callback, HdmiCec.RESULT_TARGET_NOT_AVAILABLE);
71            return;
72        }
73        mService.removeAction(DeviceSelectAction.class);
74        mService.addAndStartAction(new DeviceSelectAction(mService, mAddress,
75                                                          mService.getPhysicalAddress(), targetDevice, callback));
76    }
77
78    private static void invokeCallback(IHdmiControlCallback callback, int result) {
79        try {
80            callback.onComplete(result);
81        } catch (RemoteException e) {
82            Slog.e(TAG, "Invoking callback failed:" + e);
83        }
84    }
85
86    @Override
87    protected boolean handleGetMenuLanguage(HdmiCecMessage message) {
88        HdmiCecMessage command = HdmiCecMessageBuilder.buildSetMenuLanguageCommand(
89                mAddress, Locale.getDefault().getISO3Language());
90        // TODO: figure out how to handle failed to get language code.
91        if (command != null) {
92            mService.sendCecCommand(command);
93        } else {
94            Slog.w(TAG, "Failed to respond to <Get Menu Language>: " + message.toString());
95        }
96        return true;
97    }
98
99    private boolean handleReportPhysicalAddress(HdmiCecMessage message) {
100        // Ignore if [Device Discovery Action] is going on.
101        if (mService.hasAction(DeviceDiscoveryAction.class)) {
102            Slog.i(TAG, "Ignore unrecognizable <Report Physical Address> "
103                    + "because Device Discovery Action is on-going:" + message);
104            return true;
105        }
106
107        int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams());
108        mService.addAndStartAction(new NewDeviceAction(mService,
109                mAddress, message.getSource(), physicalAddress));
110
111        return true;
112    }
113}
114