HdmiCecLocalDeviceTv.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.hardware.hdmi.IHdmiControlCallback; 23import android.os.RemoteException; 24import android.util.Slog; 25 26import com.android.server.hdmi.DeviceDiscoveryAction.DeviceDiscoveryCallback; 27 28import java.util.Collections; 29import java.util.List; 30import java.util.Locale; 31 32/** 33 * Represent a logical device of type TV residing in Android system. 34 */ 35final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { 36 private static final String TAG = "HdmiCecLocalDeviceTv"; 37 38 HdmiCecLocalDeviceTv(HdmiControlService service) { 39 super(service, HdmiCec.DEVICE_TV); 40 } 41 42 @Override 43 protected void onAddressAllocated(int logicalAddress) { 44 // TODO: vendor-specific initialization here. 45 46 mService.sendCecCommand(HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( 47 mAddress, mService.getPhysicalAddress(), mDeviceType)); 48 mService.sendCecCommand(HdmiCecMessageBuilder.buildDeviceVendorIdCommand( 49 mAddress, mService.getVendorId())); 50 51 launchDeviceDiscovery(); 52 // TODO: Start routing control action, device discovery action. 53 } 54 55 /** 56 * Performs the action 'device select', or 'one touch play' initiated by TV. 57 * 58 * @param targetAddress logical address of the device to select 59 * @param callback callback object to report the result with 60 */ 61 void deviceSelect(int targetAddress, IHdmiControlCallback callback) { 62 HdmiCecDeviceInfo targetDevice = mService.getDeviceInfo(targetAddress); 63 if (targetDevice == null) { 64 invokeCallback(callback, HdmiCec.RESULT_TARGET_NOT_AVAILABLE); 65 return; 66 } 67 mService.removeAction(DeviceSelectAction.class); 68 mService.addAndStartAction(new DeviceSelectAction(mService, mAddress, 69 mService.getPhysicalAddress(), targetDevice, callback)); 70 } 71 72 private static void invokeCallback(IHdmiControlCallback callback, int result) { 73 try { 74 callback.onComplete(result); 75 } catch (RemoteException e) { 76 Slog.e(TAG, "Invoking callback failed:" + e); 77 } 78 } 79 80 @Override 81 protected boolean handleGetMenuLanguage(HdmiCecMessage message) { 82 HdmiCecMessage command = HdmiCecMessageBuilder.buildSetMenuLanguageCommand( 83 mAddress, Locale.getDefault().getISO3Language()); 84 // TODO: figure out how to handle failed to get language code. 85 if (command != null) { 86 mService.sendCecCommand(command); 87 } else { 88 Slog.w(TAG, "Failed to respond to <Get Menu Language>: " + message.toString()); 89 } 90 return true; 91 } 92 93 @Override 94 protected boolean handleReportPhysicalAddress(HdmiCecMessage message) { 95 // Ignore if [Device Discovery Action] is going on. 96 if (mService.hasAction(DeviceDiscoveryAction.class)) { 97 Slog.i(TAG, "Ignore unrecognizable <Report Physical Address> " 98 + "because Device Discovery Action is on-going:" + message); 99 return true; 100 } 101 102 int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams()); 103 int logicalAddress = message.getSource(); 104 105 // If it is a new device and connected to the tail of active path, 106 // it's required to change routing path. 107 boolean requireRoutingChange = !mService.isInDeviceList(physicalAddress, logicalAddress) 108 && mService.isTailOfActivePath(physicalAddress); 109 mService.addAndStartAction(new NewDeviceAction(mService, 110 mAddress, message.getSource(), physicalAddress, 111 requireRoutingChange)); 112 return true; 113 } 114 115 @Override 116 protected boolean handleVendorSpecificCommand(HdmiCecMessage message) { 117 List<VendorSpecificAction> actions = Collections.emptyList(); 118 // TODO: Call mService.getActions(VendorSpecificAction.class) to get all the actions. 119 120 // We assume that there can be multiple vendor-specific command actions running 121 // at the same time. Pass the message to each action to see if one of them needs it. 122 for (VendorSpecificAction action : actions) { 123 if (action.processCommand(message)) { 124 return true; 125 } 126 } 127 // Handle the message here if it is not already consumed by one of the running actions. 128 // Respond with a appropriate vendor-specific command or <Feature Abort>, or create another 129 // vendor-specific action: 130 // 131 // mService.addAndStartAction(new VendorSpecificAction(mService, mAddress)); 132 // 133 // For now, simply reply with <Feature Abort> and mark it consumed by returning true. 134 mService.sendCecCommand(HdmiCecMessageBuilder.buildFeatureAbortCommand( 135 message.getDestination(), message.getSource(), message.getOpcode(), 136 HdmiConstants.ABORT_REFUSED)); 137 return true; 138 } 139 140 private void launchDeviceDiscovery() { 141 mService.clearAllDeviceInfo(); 142 // TODO: Move the following callback to HdmiLocalDeviceTv. 143 DeviceDiscoveryAction action = new DeviceDiscoveryAction(mService, mAddress, 144 new DeviceDiscoveryCallback() { 145 @Override 146 public void onDeviceDiscoveryDone(List<HdmiCecDeviceInfo> deviceInfos) { 147 for (HdmiCecDeviceInfo info : deviceInfos) { 148 mService.addCecDevice(info); 149 } 150 151 // Since we removed all devices when it's start and 152 // device discovery action does not poll local devices, 153 // we should put device info of local device manually here 154 for (HdmiCecLocalDevice device : mService.getAllLocalDevices()) { 155 mService.addCecDevice(device.getDeviceInfo()); 156 } 157 158 mService.addAndStartAction(new HotplugDetectionAction(mService, 159 mAddress)); 160 } 161 }); 162 mService.addAndStartAction(action); 163 } 164} 165