1/* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15#include "keys_input_device.h" 16 17#include <thread> 18#include "log/log.h" 19#include "updater_event.h" 20 21namespace Updater { 22enum KeyUpDownEvent { 23 EVENT_KEY_UP_VALUE, 24 EVENT_KEY_DOWN_VALUE 25}; 26 27KeysInputDevice &KeysInputDevice::GetInstance() 28{ 29 static KeysInputDevice instance; 30 return instance; 31} 32 33bool KeysInputDevice::Read(OHOS::DeviceData& data) 34{ 35 data.keyId = lastKeyId_; 36 data.state = keyState_; 37 keyState_ = OHOS::INVALID_KEY_STATE; 38 return false; 39} 40 41void KeysInputDevice::OnLongKeyPressDown() 42{ 43 static int downCount = 0; 44 ++downCount; 45 timerStop_ = false; 46 using namespace std::literals::chrono_literals; 47 std::thread t { [this, lastdownCount = downCount] () { 48 constexpr auto threshold = 2s; 49 std::this_thread::sleep_for(threshold); 50 // When the downCount of the last power key press changes, 51 // it means that the last press has been released before 52 // the timeout, then you can exit the callback directly 53 if (timerStop_ || lastdownCount != downCount) { 54 return; 55 } 56 UpdaterEvent::Invoke(UPDATER_POWER_VOLUME_DOWN_EVENT); 57 }}; 58 t.detach(); 59} 60 61void KeysInputDevice::OnLongKeyPressUp() 62{ 63 // no need to judge whether in progress page, 64 // because may press power key in progress 65 // page and release power key in other page 66 timerStop_ = true; 67 UpdaterEvent::Invoke(UPDATER_POWER_VOLUME_UP_EVENT); 68} 69 70/* 71 * LONG_PRESS_POWER_ONLY_TYPE : press power key to show long press warning 72 * others : press power key and volume key to show long press warning 73 */ 74void KeysInputDevice::SetLongPressType(const std::string &type) 75{ 76 type_ = type; 77} 78 79void KeysInputDevice::PowerDownPress(const input_event &ev) 80{ 81 if (ev.code != KEY_POWER) { 82 return; 83 } 84 bool down = ev.value == EVENT_KEY_DOWN_VALUE; 85 LOG(INFO) << "power down " << ev.code; 86 if (down) { 87 OnLongKeyPressDown(); 88 } else { 89 OnLongKeyPressUp(); 90 } 91} 92 93void KeysInputDevice::PowerVolumeDownPress(const input_event &ev) 94{ 95 static bool powerDown = false; 96 static bool volumeDown = false; 97 bool down = ev.value == EVENT_KEY_DOWN_VALUE; 98 if (ev.code == KEY_POWER) { 99 powerDown = down; 100 } else if (ev.code == KEY_VOLUMEDOWN) { 101 volumeDown = down; 102 } 103 if (powerDown && volumeDown) { 104 OnLongKeyPressDown(); 105 } else if (!down && (ev.code == KEY_POWER || ev.code == KEY_VOLUMEDOWN)) { 106 OnLongKeyPressUp(); 107 } 108} 109 110int KeysInputDevice::HandleKeyEvent(const input_event &ev, uint32_t type) 111{ 112 if (ev.type != EV_KEY || ev.code > KEY_MAX) { 113 return 0; 114 } 115 if (ev.code == BTN_TOUCH || ev.code == BTN_TOOL_FINGER) { 116 return 0; 117 } 118 if (ev.code == BTN_MOUSE || ev.code == BTN_LEFT || ev.code == BTN_RIGHT || ev.code == BTN_MIDDLE) { 119 return 0; 120 } 121 122 // KEY_VOLUMEDOWN = 114, KEY_VOLUMEUP = 115, KEY_POWER = 116 123 if (ev.code == KEY_VOLUMEDOWN || ev.code == KEY_VOLUMEUP || ev.code == KEY_POWER) { 124 keyState_ = (ev.value == EVENT_KEY_DOWN_VALUE) ? 125 OHOS::InputDevice::STATE_PRESS : OHOS::InputDevice::STATE_RELEASE; 126 } else { 127 keyState_ = ev.value; 128 } 129 130 lastKeyId_ = ev.code; 131 if (type_ == LONG_PRESS_POWER_ONLY_TYPE) { 132 PowerDownPress(ev); 133 } else { 134 PowerVolumeDownPress(ev); 135 } 136 return 0; 137} 138} // namespace Updater 139