1 /* 2 * Copyright (C) 2021-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 16 #ifndef FRAMEWORKS_INPUTMETHOD_CONTROLLER_INCLUDE_INPUT_METHOD_UTILS_H 17 #define FRAMEWORKS_INPUTMETHOD_CONTROLLER_INCLUDE_INPUT_METHOD_UTILS_H 18 19 #include <stdint.h> 20 #include <variant> 21 22 #include "global.h" 23 #include "input_attribute.h" 24 #include "iremote_object.h" 25 #include "panel_info.h" 26 #include "key_event.h" 27 28 namespace OHOS { 29 namespace MiscServices { 30 constexpr uint32_t INVALID_WINDOW_ID = 0; 31 constexpr int32_t INVALID_VALUE = -1; 32 constexpr size_t MAX_PRIVATE_COMMAND_SIZE = 32 * 1024; // 32K 33 constexpr size_t MAX_PRIVATE_COMMAND_COUNT = 5; 34 constexpr size_t MAX_SYS_PRIVATE_COMMAND_COUNT = MAX_PRIVATE_COMMAND_COUNT + 1; 35 constexpr size_t MAX_VALUE_MAP_COUNT = 256; 36 constexpr size_t MAX_ARRAY_BUFFER_MSG_ID_SIZE = 256; // 256B 37 constexpr size_t MAX_ARRAY_BUFFER_MSG_PARAM_SIZE = 128 * 1024; // 128KB 38 static constexpr uint64_t INVALID_DISPLAY_ID = -1ULL; 39 const constexpr char *SYSTEM_CMD_KEY = "sys_cmd"; 40 enum class EnterKeyType { 41 UNSPECIFIED = 0, 42 NONE, 43 GO, 44 SEARCH, 45 SEND, 46 NEXT, 47 DONE, 48 PREVIOUS, 49 NEW_LINE, 50 }; 51 52 enum class TextInputType { 53 NONE = -1, 54 TEXT = 0, 55 MULTILINE, 56 NUMBER, 57 PHONE, 58 DATETIME, 59 EMAIL_ADDRESS, 60 URL, 61 VISIBLE_PASSWORD, 62 NUMBER_PASSWORD, 63 SCREEN_LOCK_PASSWORD, 64 USER_NAME, 65 NEW_PASSWORD, 66 NUMBER_DECIMAL, 67 ONE_TIME_CODE, 68 }; 69 70 enum class Direction { 71 NONE = 0, 72 UP = 1, 73 DOWN, 74 LEFT, 75 RIGHT, 76 }; 77 78 enum class SecurityMode : int32_t { 79 BASIC = 0, 80 FULL = 1, 81 }; 82 83 enum class ExtendAction { 84 SELECT_ALL = 0, 85 CUT = 3, 86 COPY, 87 PASTE, 88 }; 89 90 enum class CapacityType: int32_t { 91 IMMERSIVE_EFFECT, 92 END, 93 }; 94 95 class Configuration { 96 public: GetEnterKeyType()97 EnterKeyType GetEnterKeyType() const 98 { 99 return enterKeyType; 100 } 101 SetEnterKeyType(EnterKeyType keyType)102 void SetEnterKeyType(EnterKeyType keyType) 103 { 104 enterKeyType = keyType; 105 } 106 GetTextInputType()107 TextInputType GetTextInputType() const 108 { 109 return textInputType; 110 } 111 SetTextInputType(TextInputType textType)112 void SetTextInputType(TextInputType textType) 113 { 114 textInputType = textType; 115 } 116 117 private: 118 EnterKeyType enterKeyType = EnterKeyType::UNSPECIFIED; 119 TextInputType textInputType = TextInputType::TEXT; 120 }; 121 122 struct CursorInfo { 123 double left = -1.0; 124 double top = -1.0; 125 double width = -1.0; 126 double height = -1.0; 127 bool operator==(const CursorInfo &info) const 128 { 129 return (left == info.left && top == info.top && width == info.width && height == info.height); 130 } 131 }; 132 133 struct CursorInfoInner : public Parcelable { 134 double left = -1.0; 135 double top = -1.0; 136 double width = -1.0; 137 double height = -1.0; 138 bool operator==(const CursorInfoInner &info) const 139 { 140 return (left == info.left && top == info.top && width == info.width && height == info.height); 141 } 142 ReadFromParcelCursorInfoInner143 bool ReadFromParcel(Parcel &in) 144 { 145 left = in.ReadDouble(); 146 top = in.ReadDouble(); 147 width = in.ReadDouble(); 148 height = in.ReadDouble(); 149 return true; 150 } 151 MarshallingCursorInfoInner152 bool Marshalling(Parcel &out) const 153 { 154 if (!out.WriteDouble(left)) { 155 return false; 156 } 157 158 if (!out.WriteDouble(top)) { 159 return false; 160 } 161 162 if (!out.WriteDouble(width)) { 163 return false; 164 } 165 166 if (!out.WriteDouble(height)) { 167 return false; 168 } 169 return true; 170 } 171 UnmarshallingCursorInfoInner172 static CursorInfoInner *Unmarshalling(Parcel &in) 173 { 174 CursorInfoInner *data = new (std::nothrow) CursorInfoInner(); 175 if (data && !data->ReadFromParcel(in)) { 176 delete data; 177 data = nullptr; 178 } 179 return data; 180 } 181 }; 182 183 class KeyEvent { }; 184 185 enum class KeyboardStatus : int32_t { 186 NONE = 0, 187 HIDE, 188 SHOW 189 }; // soft keyboard 190 191 enum Trigger : int32_t { 192 IME_APP, 193 IMF, 194 END 195 }; 196 struct PanelStatusInfo { 197 PanelInfo panelInfo; 198 bool visible { false }; 199 Trigger trigger { END }; 200 uint32_t sessionId { 0 }; 201 bool operator==(const PanelStatusInfo &info) const 202 { 203 return info.panelInfo.panelFlag == panelInfo.panelFlag && info.panelInfo.panelType == panelInfo.panelType && 204 info.visible == visible && info.trigger == trigger; 205 } 206 }; 207 208 struct PanelStatusInfoInner : public Parcelable { 209 PanelInfo panelInfo; 210 bool visible { false }; 211 Trigger trigger { END }; 212 uint32_t sessionId { 0 }; 213 bool operator==(const PanelStatusInfoInner &info) const 214 { 215 return info.panelInfo.panelFlag == panelInfo.panelFlag && info.panelInfo.panelType == panelInfo.panelType && 216 info.visible == visible && info.trigger == trigger; 217 } 218 219 bool ReadFromParcel(Parcel &in); 220 bool Marshalling(Parcel &out) const; 221 static PanelStatusInfoInner *Unmarshalling(Parcel &in); 222 }; 223 224 class FunctionKey { 225 public: GetEnterKeyType()226 EnterKeyType GetEnterKeyType() const 227 { 228 return enterKeyType; 229 } 230 SetEnterKeyType(EnterKeyType keyType)231 void SetEnterKeyType(EnterKeyType keyType) 232 { 233 enterKeyType = keyType; 234 } 235 236 private: 237 EnterKeyType enterKeyType = EnterKeyType::UNSPECIFIED; 238 }; 239 240 struct Range { 241 int32_t start = INVALID_VALUE; 242 int32_t end = INVALID_VALUE; 243 bool operator==(const Range &range) const 244 { 245 return start == range.start && end == range.end; 246 } 247 }; 248 249 struct RangeInner : public Parcelable { 250 int32_t start = INVALID_VALUE; 251 int32_t end = INVALID_VALUE; 252 bool operator==(const RangeInner &range) const 253 { 254 return start == range.start && end == range.end; 255 } ReadFromParcelRangeInner256 bool ReadFromParcel(Parcel &in) 257 { 258 start = in.ReadInt32(); 259 end = in.ReadInt32(); 260 return true; 261 } MarshallingRangeInner262 bool Marshalling(Parcel &out) const 263 { 264 if (!out.WriteInt32(start)) { 265 return false; 266 } 267 268 if (!out.WriteInt32(end)) { 269 return false; 270 } 271 return true; 272 } UnmarshallingRangeInner273 static RangeInner *Unmarshalling(Parcel &in) 274 { 275 RangeInner *data = new (std::nothrow) RangeInner(); 276 if (data && !data->ReadFromParcel(in)) { 277 delete data; 278 data = nullptr; 279 } 280 return data; 281 } 282 }; 283 284 struct TextSelection { 285 int32_t oldBegin = INVALID_VALUE; 286 int32_t oldEnd = INVALID_VALUE; 287 int32_t newBegin = INVALID_VALUE; 288 int32_t newEnd = INVALID_VALUE; 289 }; 290 291 struct TextSelectionInner : public Parcelable { 292 int32_t oldBegin = INVALID_VALUE; 293 int32_t oldEnd = INVALID_VALUE; 294 int32_t newBegin = INVALID_VALUE; 295 int32_t newEnd = INVALID_VALUE; 296 297 bool ReadFromParcel(Parcel &in); 298 bool Marshalling(Parcel &out) const; 299 static TextSelectionInner *Unmarshalling(Parcel &in); 300 }; 301 302 enum PrivateDataValueType : int32_t { 303 VALUE_TYPE_STRING = 0, 304 VALUE_TYPE_BOOL, 305 VALUE_TYPE_NUMBER 306 }; 307 using PrivateDataValue = std::variant<std::string, bool, int32_t>; 308 309 enum class RequestKeyboardReason : int32_t { 310 NONE = 0, // no event reason 311 MOUSE = 1, // user triggered mouse event 312 TOUCH = 2, // user triggered touch event 313 OTHER = 20 // other reason 314 }; 315 316 using ValueMap = std::unordered_map<std::string, PrivateDataValue>; 317 318 struct Value : public Parcelable { ValueValue319 Value(const std::unordered_map<std::string, PrivateDataValue>& map) : valueMap(map) {} 320 Value() = default; 321 bool ReadFromParcel(Parcel &in); 322 bool Marshalling(Parcel &out) const override; 323 static Value *Unmarshalling(Parcel &in); 324 325 ValueMap valueMap; 326 }; 327 328 struct KeyEventValue : public Parcelable { 329 bool ReadFromParcel(Parcel &in); 330 bool Marshalling(Parcel &out) const override; 331 static KeyEventValue *Unmarshalling(Parcel &in); 332 333 std::shared_ptr<MMI::KeyEvent> event; 334 }; 335 struct TextTotalConfig { 336 public: 337 InputAttribute inputAttribute = {}; 338 CursorInfo cursorInfo = {}; 339 TextSelection textSelection = {}; 340 uint32_t windowId = INVALID_WINDOW_ID; 341 double positionY = 0; 342 double height = 0; 343 std::unordered_map<std::string, PrivateDataValue> privateCommand = {}; 344 RequestKeyboardReason requestKeyboardReason = RequestKeyboardReason::NONE; 345 sptr<IRemoteObject> abilityToken { nullptr }; 346 bool isSimpleKeyboardEnabled { false }; // indicates enable basic keyboard or not 347 ToStringTextTotalConfig348 std::string ToString() const 349 { 350 std::string config; 351 config.append("pattern/enterKey/preview: " + std::to_string(inputAttribute.inputPattern) + "/" + 352 std::to_string(inputAttribute.enterKeyType) + "/" + std::to_string(inputAttribute.isTextPreviewSupported)); 353 config.append(" windowId/y/height: " + std::to_string(windowId) + "/" + std::to_string(positionY) + "/" + 354 std::to_string(height)); 355 config.append( 356 " oldRange: " + std::to_string(textSelection.oldBegin) + "/" + std::to_string(textSelection.oldEnd)); 357 config.append( 358 " newRange: " + std::to_string(textSelection.newBegin) + "/" + std::to_string(textSelection.newEnd)); 359 config.append(" cursor: " + std::to_string(cursorInfo.left) + "/" + std::to_string(cursorInfo.top) + "/" + 360 std::to_string(cursorInfo.width) + "/" + std::to_string(cursorInfo.height)); 361 return config; 362 } 363 }; 364 365 struct TextTotalConfigInner : public Parcelable { 366 public: 367 InputAttributeInner inputAttribute = {}; 368 CursorInfoInner cursorInfo = {}; 369 TextSelectionInner textSelection = {}; 370 uint32_t windowId = INVALID_WINDOW_ID; 371 double positionY = 0; 372 double height = 0; 373 Value commandValue; 374 RequestKeyboardReason requestKeyboardReason = RequestKeyboardReason::NONE; 375 bool isSimpleKeyboardEnabled = false; 376 sptr<IRemoteObject> abilityToken { nullptr }; 377 378 bool ReadFromParcel(Parcel &parcel); 379 bool Marshalling(Parcel &parcel) const override; 380 static TextTotalConfigInner *Unmarshalling(Parcel &parcel); 381 ToStringTextTotalConfigInner382 std::string ToString() const 383 { 384 std::string config; 385 config.append("pattern/enterKey/preview: " + std::to_string(inputAttribute.inputPattern) + "/" + 386 std::to_string(inputAttribute.enterKeyType) + "/" + std::to_string(inputAttribute.isTextPreviewSupported)); 387 config.append(" windowId/y/height: " + std::to_string(windowId) + "/" + std::to_string(positionY) + "/" + 388 std::to_string(height)); 389 config.append( 390 " oldRange: " + std::to_string(textSelection.oldBegin) + "/" + std::to_string(textSelection.oldEnd)); 391 config.append( 392 " newRange: " + std::to_string(textSelection.newBegin) + "/" + std::to_string(textSelection.newEnd)); 393 config.append(" cursor: " + std::to_string(cursorInfo.left) + "/" + std::to_string(cursorInfo.top) + "/" + 394 std::to_string(cursorInfo.width) + "/" + std::to_string(cursorInfo.height)); 395 return config; 396 } 397 }; 398 struct TextConfig { 399 InputAttribute inputAttribute = {}; 400 CursorInfo cursorInfo = {}; 401 Range range = {}; 402 uint32_t windowId = INVALID_WINDOW_ID; 403 double positionY = 0; 404 double height = 0; 405 bool newEditBox = false; 406 std::unordered_map<std::string, PrivateDataValue> privateCommand = {}; 407 sptr<IRemoteObject> abilityToken { nullptr }; 408 ToStringTextConfig409 std::string ToString() const 410 { 411 std::string config; 412 config.append("pattern/enterKey/preview: " + std::to_string(inputAttribute.inputPattern) + "/" + 413 std::to_string(inputAttribute.enterKeyType) + "/" + std::to_string(inputAttribute.isTextPreviewSupported)); 414 config.append(" windowId/y/height: " + std::to_string(windowId) + "/" + std::to_string(positionY) + "/" + 415 std::to_string(height)); 416 config.append(" range: " + std::to_string(range.start) + "/" + std::to_string(range.end)); 417 config.append(" cursor: " + std::to_string(cursorInfo.left) + "/" + std::to_string(cursorInfo.top) + "/" + 418 std::to_string(cursorInfo.width) + "/" + std::to_string(cursorInfo.height)); 419 return config; 420 } 421 IsPrivateCommandValidTextConfig422 static bool IsPrivateCommandValid(const std::unordered_map<std::string, PrivateDataValue> &privateCommand) 423 { 424 size_t privateCommandSize = privateCommand.size(); 425 size_t maxSize = 426 IsSystemPrivateCommand(privateCommand) ? MAX_SYS_PRIVATE_COMMAND_COUNT : MAX_PRIVATE_COMMAND_COUNT; 427 if (privateCommandSize == 0 || privateCommandSize > maxSize) { 428 IMSA_HILOGE("privateCommand size must more than 0 and less than 5."); 429 return false; 430 } 431 size_t totalSize = 0; 432 for (const auto &iter : privateCommand) { 433 size_t keySize = iter.first.size(); 434 size_t idx = iter.second.index(); 435 size_t valueSize = 0; 436 437 if (idx == static_cast<size_t>(PrivateDataValueType::VALUE_TYPE_STRING)) { 438 auto stringValue = std::get_if<std::string>(&iter.second); 439 if (stringValue == nullptr) { 440 IMSA_HILOGE("get stringValue failed."); 441 return false; 442 } 443 valueSize = (*stringValue).size(); 444 } else if (idx == static_cast<size_t>(PrivateDataValueType::VALUE_TYPE_BOOL)) { 445 valueSize = sizeof(bool); 446 } else if (idx == static_cast<size_t>(PrivateDataValueType::VALUE_TYPE_NUMBER)) { 447 valueSize = sizeof(int32_t); 448 } 449 totalSize = totalSize + keySize + valueSize; 450 } 451 if (totalSize > MAX_PRIVATE_COMMAND_SIZE) { 452 IMSA_HILOGE("totalSize : %{public}zu", totalSize); 453 return false; 454 } 455 return true; 456 } IsSystemPrivateCommandTextConfig457 static bool IsSystemPrivateCommand(const std::unordered_map<std::string, PrivateDataValue> &privateCommand) 458 { 459 IMSA_HILOGD("in."); 460 size_t privateCommandSize = privateCommand.size(); 461 if (privateCommandSize == 0 || privateCommandSize > MAX_PRIVATE_COMMAND_COUNT) { 462 IMSA_HILOGE("privateCommand size must more than 0 and less than 5."); 463 return false; 464 } 465 auto it = privateCommand.find(SYSTEM_CMD_KEY); 466 if (it != privateCommand.end()) { 467 // if privateCommand has the key system_cmd and value is 1, it's a system privateCommand. 468 if (it->second.index() == static_cast<size_t>(PrivateDataValueType::VALUE_TYPE_NUMBER)) { 469 auto numberValue = std::get_if<int32_t>(&it->second); 470 if (numberValue == nullptr) { 471 IMSA_HILOGE("get stringValue failed."); 472 return false; 473 } 474 return *numberValue == 1; 475 } 476 } 477 return false; 478 } 479 }; 480 481 enum class InputType : int32_t { 482 NONE = -1, 483 CAMERA_INPUT = 0, 484 SECURITY_INPUT, 485 VOICE_INPUT, 486 VOICEKB_INPUT, 487 END 488 }; 489 490 enum class SwitchTrigger : uint32_t { 491 CURRENT_IME = 0, 492 SYSTEM_APP, 493 IMSA, 494 NATIVE_SA 495 }; 496 497 struct ArrayBuffer : public Parcelable { 498 size_t jsArgc = 0; 499 std::string msgId; 500 std::vector<uint8_t> msgParam; IsSizeValidArrayBuffer501 static bool IsSizeValid(const ArrayBuffer &arrayBuffer) 502 { 503 if (arrayBuffer.msgId.size() > MAX_ARRAY_BUFFER_MSG_ID_SIZE) { 504 IMSA_HILOGE("Invalid msgId size: %{public}zu.", arrayBuffer.msgId.size()); 505 return false; 506 } 507 if (arrayBuffer.msgParam.size() > MAX_ARRAY_BUFFER_MSG_PARAM_SIZE) { 508 IMSA_HILOGE("Invalid msgParam size: %{public}zu.", arrayBuffer.msgParam.size()); 509 return false; 510 } 511 return true; 512 } 513 bool operator==(const ArrayBuffer &arrayBuffer) const 514 { 515 return jsArgc == arrayBuffer.jsArgc && msgId == arrayBuffer.msgId && msgParam == arrayBuffer.msgParam; 516 } 517 bool ReadFromParcel(Parcel &in); 518 bool Marshalling(Parcel &out) const; 519 static ArrayBuffer *Unmarshalling(Parcel &in); 520 }; 521 522 struct AttachOptions { 523 bool isShowKeyboard = false; 524 bool isSimpleKeyboardEnabled = false; 525 RequestKeyboardReason requestKeyboardReason { RequestKeyboardReason::NONE }; 526 }; 527 struct ImfCallingWindowInfo { 528 uint32_t windowId = INVALID_WINDOW_ID; 529 uint64_t displayId = 0; 530 }; 531 532 struct DetachOptions { 533 uint32_t sessionId{ 0 }; 534 bool isUnbindFromClient{ false }; 535 bool isInactiveClient{ false }; 536 bool isNotifyClientAsync{ false }; 537 }; 538 539 enum class ResponseDataType : uint64_t { NONE_TYPE = 0, STRING_TYPE, INT32_TYPE }; 540 541 using ResponseData = std::variant<std::monostate, std::string, int32_t>; 542 543 struct ResponseDataInner : public Parcelable { 544 bool ReadFromParcel(Parcel &in); 545 bool Marshalling(Parcel &out) const override; UnmarshallingResponseDataInner546 static ResponseDataInner *Unmarshalling(Parcel &in) 547 { 548 ResponseDataInner *data = new (std::nothrow) ResponseDataInner(); 549 if (data != nullptr && !data->ReadFromParcel(in)) { 550 delete data; 551 data = nullptr; 552 } 553 return data; 554 } 555 ResponseData rspData = std::monostate{}; 556 }; 557 } // namespace MiscServices 558 } // namespace OHOS 559 #endif // FRAMEWORKS_INPUTMETHOD_CONTROLLER_INCLUDE_INPUT_METHOD_UTILS_H 560