1a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park/* 2a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park * Copyright (C) 2016 The Android Open Source Project 3a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park * 4a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park * Licensed under the Apache License, Version 2.0 (the "License"); 5a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park * you may not use this file except in compliance with the License. 6a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park * You may obtain a copy of the License at 7a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park * 8a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park * http://www.apache.org/licenses/LICENSE-2.0 9a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park * 10a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park * Unless required by applicable law or agreed to in writing, software 11a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park * distributed under the License is distributed on an "AS IS" BASIS, 12a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park * See the License for the specific language governing permissions and 14a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park * limitations under the License. 15a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park */ 16a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Parkpackage com.android.car.hal; 17a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park 18cfe93105f637c2822da113308f113ed418d0b319Pavel Maltsevimport static android.hardware.automotive.vehicle.V2_0.VehicleProperty.HW_KEY_INPUT; 190d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev 20cfe93105f637c2822da113308f113ed418d0b319Pavel Maltsevimport android.hardware.automotive.vehicle.V2_0.VehicleDisplay; 21cfe93105f637c2822da113308f113ed418d0b319Pavel Maltsevimport android.hardware.automotive.vehicle.V2_0.VehicleHwKeyInputAction; 22cfe93105f637c2822da113308f113ed418d0b319Pavel Maltsevimport android.hardware.automotive.vehicle.V2_0.VehiclePropConfig; 23cfe93105f637c2822da113308f113ed418d0b319Pavel Maltsevimport android.hardware.automotive.vehicle.V2_0.VehiclePropValue; 24338cef872d82a82c085f090472b38f568650ee66Pavel Maltsevimport android.os.SystemClock; 25a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Parkimport android.util.Log; 26338cef872d82a82c085f090472b38f568650ee66Pavel Maltsevimport android.util.SparseLongArray; 27338cef872d82a82c085f090472b38f568650ee66Pavel Maltsevimport android.view.InputDevice; 28a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Parkimport android.view.KeyEvent; 29a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park 30a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Parkimport com.android.car.CarLog; 31a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park 32a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Parkimport java.io.PrintWriter; 330d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport java.util.Collection; 34a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Parkimport java.util.LinkedList; 35a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Parkimport java.util.List; 36a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park 37a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Parkpublic class InputHalService extends HalServiceBase { 38a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park 390d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev public static final int DISPLAY_MAIN = VehicleDisplay.MAIN; 400d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev public static final int DISPLAY_INSTRUMENT_CLUSTER = VehicleDisplay.INSTRUMENT_CLUSTER; 410d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev private final VehicleHal mHal; 42a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park 43a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park public interface InputListener { 44a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park void onKeyEvent(KeyEvent event, int targetDisplay); 45a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park } 46a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park 47a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park private static final boolean DBG = false; 48a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park 49a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park private boolean mKeyInputSupported = false; 50a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park private InputListener mListener; 51338cef872d82a82c085f090472b38f568650ee66Pavel Maltsev private final SparseLongArray mKeyDownTimes = new SparseLongArray(); 52a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park 530d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev public InputHalService(VehicleHal hal) { 540d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev mHal = hal; 550d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev } 560d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev 57a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park public void setInputListener(InputListener listener) { 58a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park synchronized (this) { 59a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park if (!mKeyInputSupported) { 60a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park Log.w(CarLog.TAG_INPUT, "input listener set while key input not supported"); 61a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park return; 62a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park } 63a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park mListener = listener; 64a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park } 6579d5e12ad8708c1f7f7f1a60aaeb349ac7ed0f7bPavel Maltsev mHal.subscribeProperty(this, HW_KEY_INPUT); 66a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park } 67a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park 68a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park public synchronized boolean isKeyInputSupported() { 69a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park return mKeyInputSupported; 70a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park } 71a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park 72a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park @Override 73a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park public void init() { 74a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park } 75a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park 76a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park @Override 77a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park public void release() { 78a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park synchronized (this) { 79a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park mListener = null; 80a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park mKeyInputSupported = false; 81a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park } 82a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park } 83a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park 84a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park @Override 850d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev public Collection<VehiclePropConfig> takeSupportedProperties( 860d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev Collection<VehiclePropConfig> allProperties) { 870d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev List<VehiclePropConfig> supported = new LinkedList<>(); 88a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park for (VehiclePropConfig p: allProperties) { 890d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev if (p.prop == HW_KEY_INPUT) { 90a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park supported.add(p); 91a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park synchronized (this) { 92a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park mKeyInputSupported = true; 93a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park } 94a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park } 95a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park } 96a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park return supported; 97a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park } 98a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park 99a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park @Override 100a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park public void handleHalEvents(List<VehiclePropValue> values) { 1010d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev InputListener listener; 102a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park synchronized (this) { 103a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park listener = mListener; 104a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park } 105a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park if (listener == null) { 106a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park Log.w(CarLog.TAG_INPUT, "Input event while listener is null"); 107a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park return; 108a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park } 109a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park for (VehiclePropValue v : values) { 1100d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev if (v.prop != HW_KEY_INPUT) { 111a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park Log.e(CarLog.TAG_INPUT, "Wrong event dispatched, prop:0x" + 1120d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev Integer.toHexString(v.prop)); 113a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park continue; 114a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park } 1150d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev int action = (v.value.int32Values.get(0) == VehicleHwKeyInputAction.ACTION_DOWN) ? 116a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park KeyEvent.ACTION_DOWN : KeyEvent.ACTION_UP; 1170d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev int code = v.value.int32Values.get(1); 1180d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev int display = v.value.int32Values.get(2); 119a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park if (DBG) { 1200d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev Log.i(CarLog.TAG_INPUT, "hal event code:" + code + ", action:" + action + 1210d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev ", display:" + display); 122a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park } 123338cef872d82a82c085f090472b38f568650ee66Pavel Maltsev 124338cef872d82a82c085f090472b38f568650ee66Pavel Maltsev dispatchKeyEvent(listener, action, code, display); 125338cef872d82a82c085f090472b38f568650ee66Pavel Maltsev } 126338cef872d82a82c085f090472b38f568650ee66Pavel Maltsev } 127338cef872d82a82c085f090472b38f568650ee66Pavel Maltsev 128338cef872d82a82c085f090472b38f568650ee66Pavel Maltsev private void dispatchKeyEvent(InputListener listener, int action, int code, int display) { 129338cef872d82a82c085f090472b38f568650ee66Pavel Maltsev long eventTime = SystemClock.uptimeMillis(); 130338cef872d82a82c085f090472b38f568650ee66Pavel Maltsev 131338cef872d82a82c085f090472b38f568650ee66Pavel Maltsev if (action == KeyEvent.ACTION_DOWN) { 132338cef872d82a82c085f090472b38f568650ee66Pavel Maltsev mKeyDownTimes.put(code, eventTime); 133a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park } 134338cef872d82a82c085f090472b38f568650ee66Pavel Maltsev 135338cef872d82a82c085f090472b38f568650ee66Pavel Maltsev long downTime = action == KeyEvent.ACTION_UP 136338cef872d82a82c085f090472b38f568650ee66Pavel Maltsev ? mKeyDownTimes.get(code, eventTime) : eventTime; 137338cef872d82a82c085f090472b38f568650ee66Pavel Maltsev 138338cef872d82a82c085f090472b38f568650ee66Pavel Maltsev KeyEvent event = KeyEvent.obtain( 139338cef872d82a82c085f090472b38f568650ee66Pavel Maltsev downTime, 140338cef872d82a82c085f090472b38f568650ee66Pavel Maltsev eventTime, 141338cef872d82a82c085f090472b38f568650ee66Pavel Maltsev action, 142338cef872d82a82c085f090472b38f568650ee66Pavel Maltsev code, 143338cef872d82a82c085f090472b38f568650ee66Pavel Maltsev 0 /* repeat */, 144338cef872d82a82c085f090472b38f568650ee66Pavel Maltsev 0 /* meta state */, 145338cef872d82a82c085f090472b38f568650ee66Pavel Maltsev 0 /* deviceId*/, 146338cef872d82a82c085f090472b38f568650ee66Pavel Maltsev 0 /* scancode */, 147338cef872d82a82c085f090472b38f568650ee66Pavel Maltsev 0 /* flags */, 148338cef872d82a82c085f090472b38f568650ee66Pavel Maltsev InputDevice.SOURCE_CLASS_BUTTON, 149338cef872d82a82c085f090472b38f568650ee66Pavel Maltsev null /* characters */); 150338cef872d82a82c085f090472b38f568650ee66Pavel Maltsev 151338cef872d82a82c085f090472b38f568650ee66Pavel Maltsev listener.onKeyEvent(event, display); 152338cef872d82a82c085f090472b38f568650ee66Pavel Maltsev event.recycle(); 153a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park } 154a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park 155a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park @Override 156a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park public void dump(PrintWriter writer) { 157a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park writer.println("*Input HAL*"); 158a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park writer.println("mKeyInputSupported:" + mKeyInputSupported); 159a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park } 160a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park 161a28d7b201584823286f26e21a9f30d07c416eb3eKeun-young Park} 162