HdmiCecLocalDevice.java revision 092b445ef898e3c1e5b2918b554480940f0f5a28
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 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            default:
92                return false;
93        }
94    }
95
96    protected boolean handleGivePhysicalAddress() {
97        int physicalAddress = mService.getPhysicalAddress();
98        HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
99                mAddress, physicalAddress, mDeviceType);
100        mService.sendCecCommand(cecMessage);
101        return true;
102    }
103
104    protected boolean handleGiveDeviceVendorId() {
105        int vendorId = mService.getVendorId();
106        HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildDeviceVendorIdCommand(
107                mAddress, vendorId);
108        mService.sendCecCommand(cecMessage);
109        return true;
110    }
111
112    protected boolean handleGetCecVersion(HdmiCecMessage message) {
113        int version = mService.getCecVersion();
114        HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildCecVersion(message.getDestination(),
115                message.getSource(), version);
116        mService.sendCecCommand(cecMessage);
117        return true;
118    }
119
120    protected boolean handleGetMenuLanguage(HdmiCecMessage message) {
121        Slog.w(TAG, "Only TV can handle <Get Menu Language>:" + message.toString());
122        mService.sendCecCommand(
123                HdmiCecMessageBuilder.buildFeatureAbortCommand(mAddress,
124                        message.getSource(), HdmiCec.MESSAGE_GET_MENU_LANGUAGE,
125                        HdmiConstants.ABORT_UNRECOGNIZED_MODE));
126        return true;
127    }
128
129    protected boolean handleGiveOsdName(HdmiCecMessage message) {
130        // Note that since this method is called after logical address allocation is done,
131        // mDeviceInfo should not be null.
132        HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildSetOsdNameCommand(
133                mAddress, message.getSource(), mDeviceInfo.getDisplayName());
134        if (cecMessage != null) {
135            mService.sendCecCommand(cecMessage);
136        } else {
137            Slog.w(TAG, "Failed to build <Get Osd Name>:" + mDeviceInfo.getDisplayName());
138        }
139        return true;
140    }
141
142    final void handleAddressAllocated(int logicalAddress) {
143        mAddress = mPreferredAddress = logicalAddress;
144        onAddressAllocated(logicalAddress);
145    }
146
147    HdmiCecDeviceInfo getDeviceInfo() {
148        return mDeviceInfo;
149    }
150
151    void setDeviceInfo(HdmiCecDeviceInfo info) {
152        mDeviceInfo = info;
153    }
154
155    // Returns true if the logical address is same as the argument.
156    boolean isAddressOf(int addr) {
157        return addr == mAddress;
158    }
159
160    // Resets the logical address to unregistered(15), meaning the logical device is invalid.
161    void clearAddress() {
162        mAddress = HdmiCec.ADDR_UNREGISTERED;
163    }
164
165    void setPreferredAddress(int addr) {
166        mPreferredAddress = addr;
167    }
168
169    int getPreferredAddress() {
170        return mPreferredAddress;
171    }
172}
173