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