HdmiCecLocalDevice.java revision 60cffce420db4c3395f86d3b9bb36003adf26f5d
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.HdmiCec;
20import android.hardware.hdmi.HdmiCecDeviceInfo;
21import android.hardware.hdmi.HdmiCecMessage;
22import android.util.Slog;
23
24/**
25 * Class that models a logical CEC device hosted in this system. Handles initialization,
26 * CEC commands that call for actions customized per device type.
27 */
28abstract class HdmiCecLocalDevice {
29    private static final String TAG = "HdmiCecLocalDevice";
30
31    protected final HdmiControlService mService;
32    protected final int mDeviceType;
33    protected int mAddress;
34    protected int mPreferredAddress;
35    protected HdmiCecDeviceInfo mDeviceInfo;
36
37    protected HdmiCecLocalDevice(HdmiControlService service, int deviceType) {
38        mService = service;
39        mDeviceType = deviceType;
40        mAddress = HdmiCec.ADDR_UNREGISTERED;
41    }
42
43    // Factory method that returns HdmiCecLocalDevice of corresponding type.
44    static HdmiCecLocalDevice create(HdmiControlService service, int deviceType) {
45        switch (deviceType) {
46        case HdmiCec.DEVICE_TV:
47            return new HdmiCecLocalDeviceTv(service);
48        case HdmiCec.DEVICE_PLAYBACK:
49            return new HdmiCecLocalDevicePlayback(service);
50        default:
51            return null;
52        }
53    }
54
55    void init() {
56        mPreferredAddress = HdmiCec.ADDR_UNREGISTERED;
57        // TODO: load preferred address from permanent storage.
58    }
59
60    /**
61     * Called once a logical address of the local device is allocated.
62     */
63    protected abstract void onAddressAllocated(int logicalAddress);
64
65    /**
66     * Dispatch incoming message.
67     *
68     * @param message incoming message
69     * @return true if consumed a message; otherwise, return false.
70     */
71    final boolean dispatchMessage(HdmiCecMessage message) {
72        int dest = message.getDestination();
73        if (dest != mAddress && dest != HdmiCec.ADDR_BROADCAST) {
74            return false;
75        }
76        return onMessage(message);
77    }
78
79    protected final boolean onMessage(HdmiCecMessage message) {
80        switch (message.getOpcode()) {
81            case HdmiCec.MESSAGE_GET_MENU_LANGUAGE:
82                return handleGetMenuLanguage(message);
83            case HdmiCec.MESSAGE_GIVE_PHYSICAL_ADDRESS:
84                return handleGivePhysicalAddress();
85            case HdmiCec.MESSAGE_GIVE_OSD_NAME:
86                return handleGiveOsdName(message);
87            case HdmiCec.MESSAGE_GIVE_DEVICE_VENDOR_ID:
88                return handleGiveDeviceVendorId();
89            case HdmiCec.MESSAGE_GET_CEC_VERSION:
90                return handleGetCecVersion(message);
91            case HdmiCec.MESSAGE_REPORT_PHYSICAL_ADDRESS:
92                return handleReportPhysicalAddress(message);
93            default:
94                return false;
95        }
96    }
97
98    protected boolean handleGivePhysicalAddress() {
99        int physicalAddress = mService.getPhysicalAddress();
100        HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
101                mAddress, physicalAddress, mDeviceType);
102        mService.sendCecCommand(cecMessage);
103        return true;
104    }
105
106    protected boolean handleGiveDeviceVendorId() {
107        int vendorId = mService.getVendorId();
108        HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildDeviceVendorIdCommand(
109                mAddress, vendorId);
110        mService.sendCecCommand(cecMessage);
111        return true;
112    }
113
114    protected boolean handleGetCecVersion(HdmiCecMessage message) {
115        int version = mService.getCecVersion();
116        HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildCecVersion(message.getDestination(),
117                message.getSource(), version);
118        mService.sendCecCommand(cecMessage);
119        return true;
120    }
121
122    protected boolean handleGetMenuLanguage(HdmiCecMessage message) {
123        Slog.w(TAG, "Only TV can handle <Get Menu Language>:" + message.toString());
124        mService.sendCecCommand(
125                HdmiCecMessageBuilder.buildFeatureAbortCommand(mAddress,
126                        message.getSource(), HdmiCec.MESSAGE_GET_MENU_LANGUAGE,
127                        HdmiConstants.ABORT_UNRECOGNIZED_MODE));
128        return true;
129    }
130
131    protected boolean handleGiveOsdName(HdmiCecMessage message) {
132        // Note that since this method is called after logical address allocation is done,
133        // mDeviceInfo should not be null.
134        HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildSetOsdNameCommand(
135                mAddress, message.getSource(), mDeviceInfo.getDisplayName());
136        if (cecMessage != null) {
137            mService.sendCecCommand(cecMessage);
138        } else {
139            Slog.w(TAG, "Failed to build <Get Osd Name>:" + mDeviceInfo.getDisplayName());
140        }
141        return true;
142    }
143
144    protected boolean handleVendorSpecificCommand(HdmiCecMessage message) {
145        return false;
146    }
147
148    protected boolean handleReportPhysicalAddress(HdmiCecMessage message) {
149        return false;
150    }
151
152    final void handleAddressAllocated(int logicalAddress) {
153        mAddress = mPreferredAddress = logicalAddress;
154        onAddressAllocated(logicalAddress);
155    }
156
157    HdmiCecDeviceInfo getDeviceInfo() {
158        return mDeviceInfo;
159    }
160
161    void setDeviceInfo(HdmiCecDeviceInfo info) {
162        mDeviceInfo = info;
163    }
164
165    // Returns true if the logical address is same as the argument.
166    boolean isAddressOf(int addr) {
167        return addr == mAddress;
168    }
169
170    // Resets the logical address to unregistered(15), meaning the logical device is invalid.
171    void clearAddress() {
172        mAddress = HdmiCec.ADDR_UNREGISTERED;
173    }
174
175    void setPreferredAddress(int addr) {
176        mPreferredAddress = addr;
177    }
178
179    int getPreferredAddress() {
180        return mPreferredAddress;
181    }
182}
183