HdmiCecLocalDevice.java revision 0a3316bcfdac9f5f40d1349d97d10329c70f7e30
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 protected boolean handleVendorSpecificCommand(HdmiCecMessage message) { 143 return false; 144 } 145 146 final void handleAddressAllocated(int logicalAddress) { 147 mAddress = mPreferredAddress = logicalAddress; 148 onAddressAllocated(logicalAddress); 149 } 150 151 HdmiCecDeviceInfo getDeviceInfo() { 152 return mDeviceInfo; 153 } 154 155 void setDeviceInfo(HdmiCecDeviceInfo info) { 156 mDeviceInfo = info; 157 } 158 159 // Returns true if the logical address is same as the argument. 160 boolean isAddressOf(int addr) { 161 return addr == mAddress; 162 } 163 164 // Resets the logical address to unregistered(15), meaning the logical device is invalid. 165 void clearAddress() { 166 mAddress = HdmiCec.ADDR_UNREGISTERED; 167 } 168 169 void setPreferredAddress(int addr) { 170 mPreferredAddress = addr; 171 } 172 173 int getPreferredAddress() { 174 return mPreferredAddress; 175 } 176} 177