NewDeviceAction.java revision c70d2295dd3fb87ce8c81c704688d1ad05043b4d
194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood/* 294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * Copyright (C) 2014 The Android Open Source Project 394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * 494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License"); 594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * you may not use this file except in compliance with the License. 694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * You may obtain a copy of the License at 794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * 894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * http://www.apache.org/licenses/LICENSE-2.0 994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * 1094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * Unless required by applicable law or agreed to in writing, software 1194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS, 1294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * See the License for the specific language governing permissions and 1494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * limitations under the License. 15399b6c3bbc0d887ab016a8bb686ff16d36edc6c8Arve Hjønnevåg */ 169b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescupackage com.android.server.hdmi; 179b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu 1894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodimport android.hardware.hdmi.HdmiCec; 1994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodimport android.hardware.hdmi.HdmiCecDeviceInfo; 20399b6c3bbc0d887ab016a8bb686ff16d36edc6c8Arve Hjønnevågimport android.hardware.hdmi.HdmiCecMessage; 2194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodimport android.util.Slog; 2294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 2394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodimport java.io.UnsupportedEncodingException; 2494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 2594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood/** 2694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * Feature action that discovers the information of a newly found logical device. 2794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * 289b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu * This action is created when receiving <Report Physical Address>, a CEC command a newly 2994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * connected HDMI-CEC device broadcasts to announce its advent. Additional commands are issued in 305fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu * this action to gather more information on the device such as OSD name and device vendor ID. 315fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu * 3294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * <p>The result is made in the form of {@link HdmiCecDeviceInfo} object, and passed to service 3394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * for the management through its life cycle. 3494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * 3594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * <p>Package-private, accessed by {@link HdmiControlService} only. 36e5245cbf5d4e830cf605ef07f5d284d7c5d2867eArve Hjønnevåg */ 37e5245cbf5d4e830cf605ef07f5d284d7c5d2867eArve Hjønnevågfinal class NewDeviceAction extends FeatureAction { 3894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 3994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood private static final String TAG = "NewDeviceAction"; 4094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 4194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // State in which the action sent <Give OSD Name> and is waiting for <Set OSD Name> 4294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // that contains the name of the device for display on screen. 4394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood static final int STATE_WAITING_FOR_SET_OSD_NAME = 1; 4494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 45bcf38880c65297da58194eb0c0ce8d6e2bab7d94Serban Constantinescu // State in which the action sent <Give Device Vendor ID> and is waiting for 4694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // <Device Vendor ID> that contains the vendor ID of the device. 4794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood static final int STATE_WAITING_FOR_DEVICE_VENDOR_ID = 2; 4894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 499b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu private final int mDeviceLogicalAddress; 5094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood private final int mDevicePhysicalAddress; 5194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 5294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood private int mVendorId; 5394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood private String mDisplayName; 5494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 5594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood /** 5694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * Constructor. 575fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu * 5894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * @param service {@link HdmiControlService} instance 5994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * @param sourceAddress logical address to be used as source address 6094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * @param deviceLogicalAddress logical address of the device in interest 6194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * @param devicePhysicalAddress physical address of the device in interest 6294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood */ 6394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood NewDeviceAction(HdmiControlService service, int sourceAddress, int deviceLogicalAddress, 6494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood int devicePhysicalAddress) { 6594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood super(service, sourceAddress); 6694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood mDeviceLogicalAddress = deviceLogicalAddress; 6794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood mDevicePhysicalAddress = devicePhysicalAddress; 685fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu mVendorId = HdmiCec.UNKNOWN_VENDOR_ID; 695fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu } 7094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 715fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu @Override 7294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood public boolean start() { 7394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood sendCommand( 7494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood buildCommand(mSourceAddress, mDeviceLogicalAddress, HdmiCec.MESSAGE_GET_OSD_NAME)); 7594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood mState = STATE_WAITING_FOR_SET_OSD_NAME; 7694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood addTimer(mState, TIMEOUT_MS); 7794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return true; 7894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 7994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 8094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood @Override 8194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood public boolean processCommand(HdmiCecMessage cmd) { 829b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu // For the logical device in interest, we want two more pieces of information - 8394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // osd name and vendor id. They are requested in sequence. In case we don't 8494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood // get the expected responses (either by timeout or by receiving <feature abort> command), 855fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu // set them to a default osd name and unknown vendor id respectively. 8694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood int opcode = cmd.getOpcode(); 8794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood int src = cmd.getSource(); 8894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood byte[] params = cmd.getParams(); 8994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 9094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (mDeviceLogicalAddress != src) { 919b738bb4110926b85da65d36b2e6f1a50199ec4cSerban Constantinescu return false; 925fb1b8836aa5cf0f38b49bc7bfb8343b84fdf9bfSerban Constantinescu } 9394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 9494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (mState == STATE_WAITING_FOR_SET_OSD_NAME) { 95 if (opcode == HdmiCec.MESSAGE_SET_OSD_NAME) { 96 try { 97 mDisplayName = new String(params, "US-ASCII"); 98 } catch (UnsupportedEncodingException e) { 99 Slog.e(TAG, "Failed to get OSD name: " + e.getMessage()); 100 } 101 mState = STATE_WAITING_FOR_DEVICE_VENDOR_ID; 102 requestVendorId(); 103 return true; 104 } else if (opcode == HdmiCec.MESSAGE_FEATURE_ABORT) { 105 int requestOpcode = params[1]; 106 if (requestOpcode == HdmiCec.MESSAGE_SET_OSD_NAME) { 107 mState = STATE_WAITING_FOR_DEVICE_VENDOR_ID; 108 requestVendorId(); 109 return true; 110 } 111 } 112 } else if (mState == STATE_WAITING_FOR_DEVICE_VENDOR_ID) { 113 if (opcode == HdmiCec.MESSAGE_DEVICE_VENDOR_ID) { 114 if (params.length == 3) { 115 mVendorId = (params[0] << 16) + (params[1] << 8) + params[2]; 116 } else { 117 Slog.e(TAG, "Failed to get device vendor ID: "); 118 } 119 addDeviceInfo(); 120 finish(); 121 return true; 122 } else if (opcode == HdmiCec.MESSAGE_FEATURE_ABORT) { 123 int requestOpcode = params[1]; 124 if (requestOpcode == HdmiCec.MESSAGE_DEVICE_VENDOR_ID) { 125 addDeviceInfo(); 126 finish(); 127 return true; 128 } 129 } 130 } 131 return false; 132 } 133 134 private void requestVendorId() { 135 sendCommand(buildCommand(mSourceAddress, mDeviceLogicalAddress, 136 HdmiCec.MESSAGE_GIVE_DEVICE_VENDOR_ID)); 137 addTimer(mState, TIMEOUT_MS); 138 } 139 140 private void addDeviceInfo() { 141 if (mDisplayName == null) { 142 mDisplayName = HdmiCec.getDefaultDeviceName(mDeviceLogicalAddress); 143 } 144 mService.addDeviceInfo(new HdmiCecDeviceInfo( 145 mDeviceLogicalAddress, mDevicePhysicalAddress, 146 HdmiCec.getTypeFromAddress(mDeviceLogicalAddress), 147 mVendorId, mDisplayName)); 148 } 149 150 @Override 151 public void handleTimerEvent(int state) { 152 if (mState == STATE_NONE || mState != state) { 153 return; 154 } 155 if (state == STATE_WAITING_FOR_SET_OSD_NAME) { 156 // Osd name request timed out. Try vendor id 157 mState = STATE_WAITING_FOR_DEVICE_VENDOR_ID; 158 requestVendorId(); 159 } else if (state == STATE_WAITING_FOR_DEVICE_VENDOR_ID) { 160 // vendor id timed out. Go ahead creating the device info what we've got so far. 161 addDeviceInfo(); 162 finish(); 163 } 164 } 165} 166