NewDeviceAction.java revision 97affee67b6d88da40af41b36f02ecb2b823daff
1a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich/* 2a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich * Copyright (C) 2014 The Android Open Source Project 3a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich * 4a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich * Licensed under the Apache License, Version 2.0 (the "License"); 5a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich * you may not use this file except in compliance with the License. 6a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich * You may obtain a copy of the License at 7a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich * 8a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich * http://www.apache.org/licenses/LICENSE-2.0 9a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich * 10a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich * Unless required by applicable law or agreed to in writing, software 11a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich * distributed under the License is distributed on an "AS IS" BASIS, 12a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich * See the License for the specific language governing permissions and 14a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich * limitations under the License. 15a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich */ 16a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevichpackage com.android.server.hdmi; 17a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich 18a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevichimport android.hardware.hdmi.HdmiCecDeviceInfo; 19a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevichimport android.util.Slog; 20a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich 21a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevichimport java.io.UnsupportedEncodingException; 22a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich 23a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich/** 24a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich * Feature action that discovers the information of a newly found logical device. 25a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich * 26a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich * This action is created when receiving <Report Physical Address>, a CEC command a newly 2716928bfeca8858a0acae6942fc68c14a040b92ffRomain Guy * connected HDMI-CEC device broadcasts to announce its advent. Additional commands are issued in 2816928bfeca8858a0acae6942fc68c14a040b92ffRomain Guy * this action to gather more information on the device such as OSD name and device vendor ID. 2916928bfeca8858a0acae6942fc68c14a040b92ffRomain Guy * 3016928bfeca8858a0acae6942fc68c14a040b92ffRomain Guy * <p>The result is made in the form of {@link HdmiCecDeviceInfo} object, and passed to service 3116928bfeca8858a0acae6942fc68c14a040b92ffRomain Guy * for the management through its life cycle. 321cadb25da1ed875bdd078270e642966724a0c39aMathias Agopian * 33a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich * <p>Package-private, accessed by {@link HdmiControlService} only. 34a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich */ 35a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevichfinal class NewDeviceAction extends FeatureAction { 36a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich 37a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich private static final String TAG = "NewDeviceAction"; 38a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich 39a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich // State in which the action sent <Give OSD Name> and is waiting for <Set OSD Name> 404774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall // that contains the name of the device for display on screen. 414774338bd0ad1ebe42c311fd0c72f13786b5c800Jesse Hall static final int STATE_WAITING_FOR_SET_OSD_NAME = 1; 42a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich 43a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich // State in which the action sent <Give Device Vendor ID> and is waiting for 44a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich // <Device Vendor ID> that contains the vendor ID of the device. 45a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich static final int STATE_WAITING_FOR_DEVICE_VENDOR_ID = 2; 46a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich 47a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich private final int mDeviceLogicalAddress; 48a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich private final int mDevicePhysicalAddress; 49a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich 50a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich private int mVendorId; 51a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich private String mDisplayName; 52a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich 53a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich /** 54a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich * Constructor. 55a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich * 56a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich * @param source {@link HdmiCecLocalDevice} instance 57a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich * @param deviceLogicalAddress logical address of the device in interest 58a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich * @param devicePhysicalAddress physical address of the device in interest 59a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich */ 60a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich NewDeviceAction(HdmiCecLocalDevice source, int deviceLogicalAddress, 61a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich int devicePhysicalAddress) { 62a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich super(source); 63a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich mDeviceLogicalAddress = deviceLogicalAddress; 64a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich mDevicePhysicalAddress = devicePhysicalAddress; 65a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich mVendorId = Constants.UNKNOWN_VENDOR_ID; 66a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich } 67a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich 68a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich @Override 696132b3703da76389e81d26b0023846a78b008603Jack Palevich public boolean start() { 706132b3703da76389e81d26b0023846a78b008603Jack Palevich mState = STATE_WAITING_FOR_SET_OSD_NAME; 716132b3703da76389e81d26b0023846a78b008603Jack Palevich if (mayProcessCommandIfCached(mDeviceLogicalAddress, Constants.MESSAGE_SET_OSD_NAME)) { 726132b3703da76389e81d26b0023846a78b008603Jack Palevich return true; 73a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich } 74a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich 75a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich sendCommand(HdmiCecMessageBuilder.buildGiveOsdNameCommand(getSourceAddress(), 76a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich mDeviceLogicalAddress)); 77a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich addTimer(mState, HdmiConfig.TIMEOUT_MS); 78a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich return true; 796132b3703da76389e81d26b0023846a78b008603Jack Palevich } 806132b3703da76389e81d26b0023846a78b008603Jack Palevich 816132b3703da76389e81d26b0023846a78b008603Jack Palevich @Override 826132b3703da76389e81d26b0023846a78b008603Jack Palevich public boolean processCommand(HdmiCecMessage cmd) { 836132b3703da76389e81d26b0023846a78b008603Jack Palevich // For the logical device in interest, we want two more pieces of information - 846132b3703da76389e81d26b0023846a78b008603Jack Palevich // osd name and vendor id. They are requested in sequence. In case we don't 856132b3703da76389e81d26b0023846a78b008603Jack Palevich // get the expected responses (either by timeout or by receiving <feature abort> command), 866132b3703da76389e81d26b0023846a78b008603Jack Palevich // set them to a default osd name and unknown vendor id respectively. 876132b3703da76389e81d26b0023846a78b008603Jack Palevich int opcode = cmd.getOpcode(); 886132b3703da76389e81d26b0023846a78b008603Jack Palevich int src = cmd.getSource(); 896132b3703da76389e81d26b0023846a78b008603Jack Palevich byte[] params = cmd.getParams(); 906132b3703da76389e81d26b0023846a78b008603Jack Palevich 916132b3703da76389e81d26b0023846a78b008603Jack Palevich if (mDeviceLogicalAddress != src) { 926132b3703da76389e81d26b0023846a78b008603Jack Palevich return false; 936132b3703da76389e81d26b0023846a78b008603Jack Palevich } 946132b3703da76389e81d26b0023846a78b008603Jack Palevich 956132b3703da76389e81d26b0023846a78b008603Jack Palevich if (mState == STATE_WAITING_FOR_SET_OSD_NAME) { 966132b3703da76389e81d26b0023846a78b008603Jack Palevich if (opcode == Constants.MESSAGE_SET_OSD_NAME) { 976132b3703da76389e81d26b0023846a78b008603Jack Palevich try { 986132b3703da76389e81d26b0023846a78b008603Jack Palevich mDisplayName = new String(params, "US-ASCII"); 996132b3703da76389e81d26b0023846a78b008603Jack Palevich } catch (UnsupportedEncodingException e) { 1006132b3703da76389e81d26b0023846a78b008603Jack Palevich Slog.e(TAG, "Failed to get OSD name: " + e.getMessage()); 101a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich } 102a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich requestVendorId(); 103a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich return true; 1049d4536835248525f32f1504a3d28d5bbfa0a2910Steve Block } else if (opcode == Constants.MESSAGE_FEATURE_ABORT) { 105a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich int requestOpcode = params[1] & 0xFF; 106a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich if (requestOpcode == Constants.MESSAGE_SET_OSD_NAME) { 107a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich requestVendorId(); 108a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich return true; 109a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich } 1109d4536835248525f32f1504a3d28d5bbfa0a2910Steve Block } 111a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich } else if (mState == STATE_WAITING_FOR_DEVICE_VENDOR_ID) { 1129d4536835248525f32f1504a3d28d5bbfa0a2910Steve Block if (opcode == Constants.MESSAGE_DEVICE_VENDOR_ID) { 113a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich mVendorId = HdmiUtils.threeBytesToInt(params); 114a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich addDeviceInfo(); 1159d4536835248525f32f1504a3d28d5bbfa0a2910Steve Block finish(); 116a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich return true; 1179d4536835248525f32f1504a3d28d5bbfa0a2910Steve Block } else if (opcode == Constants.MESSAGE_FEATURE_ABORT) { 118a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich int requestOpcode = params[1] & 0xFF; 119a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich if (requestOpcode == Constants.MESSAGE_DEVICE_VENDOR_ID) { 120a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich addDeviceInfo(); 1219d4536835248525f32f1504a3d28d5bbfa0a2910Steve Block finish(); 122a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich return true; 1239d4536835248525f32f1504a3d28d5bbfa0a2910Steve Block } 1249d4536835248525f32f1504a3d28d5bbfa0a2910Steve Block } 125a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich } 126a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich return false; 1279d4536835248525f32f1504a3d28d5bbfa0a2910Steve Block } 128a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich 129a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich private boolean mayProcessCommandIfCached(int destAddress, int opcode) { 130a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich HdmiCecMessage message = getCecMessageCache().getMessage(destAddress, opcode); 131a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich if (message != null) { 1326132b3703da76389e81d26b0023846a78b008603Jack Palevich return processCommand(message); 1336132b3703da76389e81d26b0023846a78b008603Jack Palevich } 1346132b3703da76389e81d26b0023846a78b008603Jack Palevich return false; 1356132b3703da76389e81d26b0023846a78b008603Jack Palevich } 1366132b3703da76389e81d26b0023846a78b008603Jack Palevich 1376132b3703da76389e81d26b0023846a78b008603Jack Palevich private void requestVendorId() { 1389d4536835248525f32f1504a3d28d5bbfa0a2910Steve Block // At first, transit to waiting status for <Device Vendor Id>. 1396132b3703da76389e81d26b0023846a78b008603Jack Palevich mState = STATE_WAITING_FOR_DEVICE_VENDOR_ID; 1406132b3703da76389e81d26b0023846a78b008603Jack Palevich // If the message is already in cache, process it. 1416132b3703da76389e81d26b0023846a78b008603Jack Palevich if (mayProcessCommandIfCached(mDeviceLogicalAddress, 1426132b3703da76389e81d26b0023846a78b008603Jack Palevich Constants.MESSAGE_DEVICE_VENDOR_ID)) { 1436132b3703da76389e81d26b0023846a78b008603Jack Palevich return; 1446132b3703da76389e81d26b0023846a78b008603Jack Palevich } 1456132b3703da76389e81d26b0023846a78b008603Jack Palevich sendCommand(HdmiCecMessageBuilder.buildGiveDeviceVendorIdCommand(getSourceAddress(), 1466132b3703da76389e81d26b0023846a78b008603Jack Palevich mDeviceLogicalAddress)); 1476132b3703da76389e81d26b0023846a78b008603Jack Palevich addTimer(mState, HdmiConfig.TIMEOUT_MS); 1486132b3703da76389e81d26b0023846a78b008603Jack Palevich } 1496132b3703da76389e81d26b0023846a78b008603Jack Palevich 1506132b3703da76389e81d26b0023846a78b008603Jack Palevich private void addDeviceInfo() { 1516132b3703da76389e81d26b0023846a78b008603Jack Palevich if (mDisplayName == null) { 1526132b3703da76389e81d26b0023846a78b008603Jack Palevich mDisplayName = HdmiUtils.getDefaultDeviceName(mDeviceLogicalAddress); 1536132b3703da76389e81d26b0023846a78b008603Jack Palevich } 1546132b3703da76389e81d26b0023846a78b008603Jack Palevich tv().addCecDevice(new HdmiCecDeviceInfo( 1556132b3703da76389e81d26b0023846a78b008603Jack Palevich mDeviceLogicalAddress, mDevicePhysicalAddress, 1566132b3703da76389e81d26b0023846a78b008603Jack Palevich HdmiUtils.getTypeFromAddress(mDeviceLogicalAddress), 1576132b3703da76389e81d26b0023846a78b008603Jack Palevich mVendorId, mDisplayName)); 1586132b3703da76389e81d26b0023846a78b008603Jack Palevich 1599d4536835248525f32f1504a3d28d5bbfa0a2910Steve Block if (HdmiUtils.getTypeFromAddress(mDeviceLogicalAddress) 1606132b3703da76389e81d26b0023846a78b008603Jack Palevich == HdmiCecDeviceInfo.DEVICE_AUDIO_SYSTEM) { 1616132b3703da76389e81d26b0023846a78b008603Jack Palevich if (tv().getSystemAudioMode()) { 1629d4536835248525f32f1504a3d28d5bbfa0a2910Steve Block addAndStartAction(new SystemAudioAutoInitiationAction(localDevice(), 1636132b3703da76389e81d26b0023846a78b008603Jack Palevich mDeviceLogicalAddress)); 1646132b3703da76389e81d26b0023846a78b008603Jack Palevich } 1659d4536835248525f32f1504a3d28d5bbfa0a2910Steve Block 1666132b3703da76389e81d26b0023846a78b008603Jack Palevich if (shouldTryArcInitiation()) { 1676132b3703da76389e81d26b0023846a78b008603Jack Palevich addAndStartAction(new RequestArcInitiationAction(localDevice(), 1686132b3703da76389e81d26b0023846a78b008603Jack Palevich mDeviceLogicalAddress)); 1696132b3703da76389e81d26b0023846a78b008603Jack Palevich } 1706132b3703da76389e81d26b0023846a78b008603Jack Palevich } 1719d4536835248525f32f1504a3d28d5bbfa0a2910Steve Block } 1726132b3703da76389e81d26b0023846a78b008603Jack Palevich 1736132b3703da76389e81d26b0023846a78b008603Jack Palevich private boolean shouldTryArcInitiation() { 1746132b3703da76389e81d26b0023846a78b008603Jack Palevich return tv().isConnectedToArcPort(mDevicePhysicalAddress) && tv().isArcFeatureEnabled(); 1756132b3703da76389e81d26b0023846a78b008603Jack Palevich } 1766132b3703da76389e81d26b0023846a78b008603Jack Palevich 1779d4536835248525f32f1504a3d28d5bbfa0a2910Steve Block @Override 1786132b3703da76389e81d26b0023846a78b008603Jack Palevich public void handleTimerEvent(int state) { 1796132b3703da76389e81d26b0023846a78b008603Jack Palevich if (mState == STATE_NONE || mState != state) { 1806132b3703da76389e81d26b0023846a78b008603Jack Palevich return; 181a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich } 182a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich if (state == STATE_WAITING_FOR_SET_OSD_NAME) { 183a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich // Osd name request timed out. Try vendor id 1846132b3703da76389e81d26b0023846a78b008603Jack Palevich requestVendorId(); 1856132b3703da76389e81d26b0023846a78b008603Jack Palevich } else if (state == STATE_WAITING_FOR_DEVICE_VENDOR_ID) { 1866132b3703da76389e81d26b0023846a78b008603Jack Palevich // vendor id timed out. Go ahead creating the device info what we've got so far. 1876132b3703da76389e81d26b0023846a78b008603Jack Palevich addDeviceInfo(); 188a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich finish(); 189a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich } 190a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich } 191a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich 192a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich boolean isActionOf(int address, int path) { 193a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich return (mDeviceLogicalAddress == address) && (mDevicePhysicalAddress == path); 194a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich } 195a2dd6cf59962e3a21a47df29b2f243e904839ba7Jack Palevich} 1966132b3703da76389e81d26b0023846a78b008603Jack Palevich