【OpenHarmony】输入法imf框架

输入法框架(IMF)模块

1. 模块概述

源码:https://gitee.com/openharmony/inputmethod_imf

1.1 功能与目标

主要功能

输入法框架(Input Method Framework,简称IMF)是OpenHarmony系统中负责输入法管理的核心子系统,其主要功能包括:

  1. 应用与输入法的桥梁:拉通应用程序和输入法应用,保证应用可以通过输入法进行文本输入
  2. 输入法生命周期管理:管理输入法的启动、停止、切换等生命周期
  3. 软键盘面板管理:控制软键盘面板的显示、隐藏、大小调整等
  4. 多用户会话管理:支持多用户场景下的输入法会话管理
  5. 输入法切换:支持用户在多个输入法之间进行切换
  6. 安全输入:支持密码输入等安全场景的特殊处理
  7. 代理输入法:支持ProxyIME模式,允许第三方应用代理输入
设计目标
  • 提供统一、稳定的输入法接口
  • 支持多种输入类型(文本、数字、密码等)
  • 保证输入法切换的流畅性
  • 确保安全输入场景的数据安全
  • 支持多屏幕、多用户场景

1.2 系统位置

在系统中的位置

输入法框架位于OpenHarmony系统的系统基础服务层,作为Misc软件服务的一部分,为上层应用提供输入能力支持。
系统基础服务层
框架层
应用层
Misc软件服务
Frameworks
APIs
桌面
设置
其他系统应用
扩展应用/三方应用
API
IDL
输入法服务 IMF模块

模块角色
  • 核心模块:作为系统输入能力的核心提供者
  • 服务提供者:以System Ability形式提供服务(SA ID: 3703)
  • 中间层:连接应用程序和输入法应用

1.3 设计思路与模式

设计思路
  1. 分层架构:采用Client-Service-IME三层架构

    • Client层:应用客户端(InputMethodController)
    • Service层:输入法服务(InputMethodSystemAbility)
    • IME层:输入法应用(InputMethodAbility)
  2. IPC通信:基于OpenHarmony的IPC机制实现跨进程通信

    • 使用IDL定义接口
    • 通过Proxy-Stub模式实现远程调用
  3. 事件驱动:采用消息队列和事件处理机制

    • 异步处理输入事件
    • 支持事件监听和回调
  4. 会话管理:基于用户的会话管理

    • 每个用户独立的PerUserSession
    • 支持多客户端并发
设计模式
设计模式 应用场景 说明
单例模式 InputMethodController、InputMethodAbility 保证全局唯一实例
代理模式 IPC通信的Proxy-Stub 实现远程对象的本地代理
观察者模式 事件监听机制 监听输入法状态变化、面板状态等
工厂模式 ImeStateManagerFactory 创建不同类型的状态管理器
状态模式 ImeStatus、ClientState 管理输入法和客户端的状态转换
策略模式 输入类型处理 根据不同输入类型采用不同策略

1.4 系统框图

输入法应用进程 (IMA)
输入法服务进程 (IMSA)
应用程序进程
IPC (IInputMethodSystemAbility)
IPC (IInputMethodCore)
InputMethodAbility (IMA)
InputMethodPanel
KeyboardListener
ImeEngineListener
InputDataChannel
InputMethodSystemAbility (SA 3703)
PerUserSession
ClientGroup
ImeData
SwitchQueue
UserSessionMgr
ImeInfoInquirer
ImeCfgManager
InputMethodController (IMC)
Attach
ShowInput
Close
OnTextChangedListener


2. 模块结构

2.1 源文件与头文件

目录结构
复制代码
/base/inputmethod/imf
├── common/                          # 公共模块
│   ├── include/                     # 公共头文件
│   │   ├── global.h                 # 全局定义和错误码
│   │   ├── message.h                # 消息定义
│   │   ├── block_queue.h            # 阻塞队列
│   │   └── ...
│   └── src/                         # 公共源文件
│
├── frameworks/                      # 框架层
│   ├── native/
│   │   ├── inputmethod_controller/  # 应用客户端模块
│   │   │   ├── include/
│   │   │   │   ├── input_method_controller.h
│   │   │   │   ├── input_client_info.h
│   │   │   │   └── ...
│   │   │   └── src/
│   │   │       ├── input_method_controller.cpp
│   │   │       └── ...
│   │   │
│   │   └── inputmethod_ability/     # 输入法客户端模块
│   │       ├── include/
│   │       │   ├── input_method_ability.h
│   │       │   ├── input_method_panel.h
│   │       │   └── ...
│   │       └── src/
│   │           ├── input_method_ability.cpp
│   │           └── ...
│   │
│   ├── js/napi/                     # JS接口层
│   └── cj/                          # CJ接口层
│
├── services/                        # 服务层
│   ├── include/
│   │   ├── input_method_system_ability.h
│   │   ├── peruser_session.h
│   │   ├── client_group.h
│   │   └── ...
│   └── src/
│       ├── input_method_system_ability.cpp
│       ├── peruser_session.cpp
│       └── ...
│
└── interfaces/                      # 接口定义
    ├── inner_api/                   # 内部API
    └── kits/c/                      # C接口
核心文件说明
文件路径 功能描述
common/include/global.h 全局错误码定义、日志宏定义
frameworks/native/inputmethod_controller/include/input_method_controller.h 应用客户端接口定义
frameworks/native/inputmethod_ability/include/input_method_ability.h 输入法能力接口定义
frameworks/native/inputmethod_ability/include/input_method_panel.h 输入法面板管理
services/include/input_method_system_ability.h 系统服务主类定义
services/include/peruser_session.h 用户会话管理
services/include/client_group.h 客户端组管理

2.2 类、结构体、函数与方法

2.2.1 核心类
InputMethodController(应用客户端)
cpp 复制代码
class InputMethodController : public RefBase, public PrivateCommandInterface {
public:
    // 单例获取
    static sptr<InputMethodController> GetInstance();
    
    // 绑定输入法
    int32_t Attach(sptr<OnTextChangedListener> listener, 
                   bool isShowKeyboard, 
                   const TextConfig &textConfig,
                   ClientType type = ClientType::INNER_KIT);
    
    // 显示/隐藏软键盘
    int32_t ShowTextInput(ClientType type = ClientType::INNER_KIT);
    int32_t HideTextInput();
    int32_t ShowSoftKeyboard(ClientType type = ClientType::INNER_KIT);
    int32_t HideSoftKeyboard();
    
    // 关闭输入法
    int32_t Close();
    
    // 光标和选择更新
    int32_t OnCursorUpdate(CursorInfo cursorInfo);
    int32_t OnSelectionChange(std::u16string text, int start, int end);
    
    // 输入法切换
    int32_t SwitchInputMethod(SwitchTrigger trigger, 
                              const std::string &name, 
                              const std::string &subName = "");
    
    // 输入法列表
    int32_t ListInputMethod(std::vector<Property> &props);
    int32_t ListInputMethodSubtype(const Property &property, 
                                   std::vector<SubProperty> &subProperties);
    
    // 获取当前输入法信息
    std::shared_ptr<Property> GetCurrentInputMethod();
    std::shared_ptr<SubProperty> GetCurrentInputMethodSubtype();
    
    // 键盘事件分发
    int32_t DispatchKeyEvent(std::shared_ptr<MMI::KeyEvent> keyEvent, 
                             KeyEventCallback callback);
    
    // 私有命令
    int32_t SendPrivateCommand(const std::unordered_map<std::string, 
                               PrivateDataValue> &privateCommand) override;
    
    // 文本预览
    int32_t SetPreviewText(const std::string &text, const Range &range);
    int32_t FinishTextPreview();
    
private:
    InputMethodController();
    ~InputMethodController();
    
    // 成员变量
    static sptr<InputMethodController> instance_;
    sptr<IInputMethodSystemAbility> abilityManager_;
    sptr<OnTextChangedListener> textListener_;
    InputClientInfo clientInfo_;
    TextConfig textConfig_;
    // ...
};
InputMethodAbility(输入法能力)
cpp 复制代码
class InputMethodAbility : public RefBase, public PrivateCommandInterface {
public:
    static InputMethodAbility &GetInstance();
    
    // 核心连接
    int32_t SetCoreAndAgent();
    int32_t InitConnect();
    
    // 文本操作
    int32_t InsertText(const std::string &text, 
                       const AsyncIpcCallBack &callback = nullptr);
    int32_t DeleteForward(int32_t length, 
                          const AsyncIpcCallBack &callback = nullptr);
    int32_t DeleteBackward(int32_t length, 
                           const AsyncIpcCallBack &callback = nullptr);
    
    // 获取文本
    int32_t GetTextBeforeCursor(int32_t number, std::u16string &text);
    int32_t GetTextAfterCursor(int32_t number, std::u16string &text);
    
    // 软键盘控制
    int32_t HideKeyboardSelf();
    
    // 面板管理
    int32_t CreatePanel(const std::shared_ptr<AbilityRuntime::Context> &context,
                        const PanelInfo &panelInfo,
                        std::shared_ptr<InputMethodPanel> &inputMethodPanel);
    int32_t DestroyPanel(const std::shared_ptr<InputMethodPanel> &inputMethodPanel);
    int32_t ShowPanel(const std::shared_ptr<InputMethodPanel> &inputMethodPanel);
    int32_t HidePanel(const std::shared_ptr<InputMethodPanel> &inputMethodPanel);
    
    // 监听器设置
    void SetImeListener(std::shared_ptr<InputMethodEngineListener> imeListener);
    void SetKdListener(std::shared_ptr<KeyboardListener> kdListener);
    
    // 状态查询
    bool IsCurrentIme();
    bool IsEnable();
    
    // 安全模式
    int32_t GetSecurityMode(int32_t &security);
    
private:
    InputMethodAbility();
    ~InputMethodAbility();
    
    // 成员变量
    sptr<IInputMethodSystemAbility> abilityManager_;
    std::shared_ptr<InputMethodEngineListener> imeListener_;
    std::shared_ptr<KeyboardListener> kdListener_;
    ConcurrentMap<PanelType, std::shared_ptr<InputMethodPanel>> panels_;
    // ...
};
InputMethodSystemAbility(系统服务)
cpp 复制代码
class InputMethodSystemAbility : public SystemAbility, 
                                  public InputMethodSystemAbilityStub {
    DECLARE_SYSTEM_ABILITY(InputMethodSystemAbility);
    
public:
    InputMethodSystemAbility(int32_t systemAbilityId, bool runOnCreate);
    
    // 输入控制
    ErrCode StartInput(const InputClientInfoInner &inputClientInfoInner,
                       std::vector<sptr<IRemoteObject>> &agents,
                       std::vector<BindImeInfo> &imeInfos) override;
    ErrCode ShowCurrentInput(uint32_t type) override;
    ErrCode HideCurrentInput() override;
    ErrCode ShowInput(const sptr<IInputClient>& client, uint32_t type) override;
    ErrCode HideInput(const sptr<IInputClient>& client) override;
    ErrCode ReleaseInput(const sptr<IInputClient>& client, uint32_t sessionId) override;
    
    // 输入法管理
    ErrCode GetCurrentInputMethod(Property& resultValue) override;
    ErrCode GetCurrentInputMethodSubtype(SubProperty& resultValue) override;
    ErrCode ListInputMethod(uint32_t status, std::vector<Property> &props) override;
    ErrCode SwitchInputMethod(const std::string &bundleName, 
                              const std::string &subName, 
                              uint32_t trigger) override;
    
    // 面板状态
    ErrCode PanelStatusChange(uint32_t status, const ImeWindowInfo &info) override;
    ErrCode IsPanelShown(const PanelInfo &panelInfo, bool &isShown) override;
    
    // IME核心设置
    ErrCode SetCoreAndAgent(const sptr<IInputMethodCore> &core, 
                            const sptr<IRemoteObject> &agent) override;
    
protected:
    void OnStart() override;
    void OnStop() override;
    
private:
    ServiceRunningState state_;
    std::shared_ptr<IdentityChecker> identityChecker_;
    int32_t userId_;
    // ...
};
PerUserSession(用户会话)
cpp 复制代码
class PerUserSession {
public:
    explicit PerUserSession(int userId);
    
    // 输入控制
    int32_t OnPrepareInput(const InputClientInfo &clientInfo);
    int32_t OnStartInput(const InputClientInfo &inputClientInfo,
                         std::vector<sptr<IRemoteObject>> &agents,
                         std::vector<BindImeInfo> &imeInfos);
    int32_t OnReleaseInput(const sptr<IInputClient> &client, uint32_t sessionId);
    
    // 显示/隐藏
    int32_t OnShowCurrentInput(uint64_t displayId);
    int32_t OnHideCurrentInput(uint64_t displayId);
    int32_t OnShowInput(sptr<IInputClient> client, int32_t requestKeyboardReason = 0);
    int32_t OnHideInput(sptr<IInputClient> client);
    
    // IME生命周期
    int32_t StartCurrentIme(bool isStopCurrentIme = false);
    int32_t StopCurrentIme();
    bool RestartIme();
    
    // 代理IME
    int32_t OnRegisterProxyIme(const sptr<IInputMethodCore> &core,
                               const sptr<IRemoteObject> &agent, int32_t pid);
    int32_t OnUnRegisteredProxyIme(UnRegisteredType type,
                                   const sptr<IInputMethodCore> &core, pid_t pid);
    
    // 焦点管理
    void OnFocused(uint64_t displayId, int32_t pid, int32_t uid);
    void OnUnfocused(uint64_t displayId, int32_t pid, int32_t uid);
    
private:
    int32_t userId_;
    std::unordered_map<ImeType, std::vector<std::shared_ptr<ImeData>>> imeData_;
    std::unordered_map<uint64_t, std::shared_ptr<ClientGroup>> clientGroupMap_;
    BlockQueue<SwitchInfo> switchQueue_;
    // ...
};
2.2.2 关键结构体
cpp 复制代码
// 输入法状态
enum class ImeStatus : uint32_t { 
    STARTING,   // 正在启动
    READY,      // 就绪
    EXITING     // 正在退出
};

// IME事件
enum class ImeEvent : uint32_t {
    START_IME,
    START_IME_TIMEOUT,
    STOP_IME,
    SET_CORE_AND_AGENT,
};

// 客户端状态
enum class ClientState : uint32_t {
    INACTIVE,
    ACTIVE
};

// IME数据
struct ImeData {
    sptr<IInputMethodCore> core{ nullptr };
    sptr<IRemoteObject> agent{ nullptr };
    sptr<InputDeathRecipient> deathRecipient{ nullptr };
    pid_t pid;
    std::shared_ptr<ImeStateManager> imeStateManager;
    ImeStatus imeStatus{ ImeStatus::STARTING };
    std::pair<std::string, std::string> ime; // bundleName, extName
    int64_t startTime{ 0 };
};

// 输入客户端信息
struct InputClientInfo {
    sptr<IInputClient> client;
    sptr<IRemoteObject> channel;
    InputAttribute attribute;
    TextTotalConfig config;
    uint32_t eventFlag;
    bool isShowKeyboard;
    ClientState state;
    ClientType type;
    // ...
};

// 面板信息
struct PanelInfo {
    PanelType panelType;
    PanelFlag panelFlag;
};

// 文本配置
struct TextConfig {
    InputAttribute inputAttribute;
    CursorInfo cursorInfo;
    Range range;
    uint32_t windowId;
    double positionY;
    double height;
    // ...
};
2.2.3 继承与多态

RefBase
InputMethodController
+GetInstance()
+Attach()
+Close()
+ShowTextInput()
InputMethodAbility
+GetInstance()
+InsertText()
+CreatePanel()
<<abstract>>
OnTextChangedListener
+InsertText()
+DeleteForward()
+DeleteBackward()
PrivateCommandInterface
TextInputClient
SystemAbility
InputMethodSystemAbility
InputMethodSystemAbilityStub
IInputMethodSystemAbility
<<abstract>>
ImeStateManager
+IsIpcNeeded()
+BeforeIpc()
+AfterIpc()
FreezeManager

2.3 类图

uses
IPC
manages
contains
stores
IPC
creates
1 1 1 * * * InputMethodController
-instance_ : sptr<InputMethodController>
-abilityManager_ : sptr<IInputMethodSystemAbility>
-textListener_ : sptr<OnTextChangedListener>
-clientInfo_ : InputClientInfo
+GetInstance() : sptr<InputMethodController>
+Attach() : int32_t
+Close() : int32_t
+ShowTextInput() : int32_t
+HideTextInput() : int32_t
+OnCursorUpdate() : int32_t
+OnSelectionChange() : int32_t
<<interface>>
OnTextChangedListener
+InsertText(text)
+DeleteForward(length)
+DeleteBackward(length)
+MoveCursor(direction)
+HandleExtendAction(action)
TextInputClient
+InsertText(text)
+DeleteForward(length)
InputMethodSystemAbility
-state_ : ServiceRunningState
-identityChecker_ : shared_ptr<IdentityChecker>
-userId_ : int32_t
+StartInput() : ErrCode
+ShowCurrentInput() : ErrCode
+HideCurrentInput() : ErrCode
+SwitchInputMethod() : ErrCode
+ListInputMethod() : ErrCode
PerUserSession
-userId_ : int32_t
-imeData_ : unordered_map
-clientGroupMap_ : unordered_map
-switchQueue_ : BlockQueue
+OnStartInput() : int32_t
+OnShowInput() : int32_t
+OnHideInput() : int32_t
+StartCurrentIme() : int32_t
+StopCurrentIme() : int32_t
ClientGroup
-displayGroupId_ : uint64_t
-mapClients_ : map
-currentClient_ : sptr<IInputClient>
+AddClientInfo() : int32_t
+RemoveClientInfo() : void
+GetCurrentClient() : sptr<IInputClient>
InputClientInfo
+client : sptr<IInputClient>
+channel : sptr<IRemoteObject>
+attribute : InputAttribute
+state : ClientState
InputMethodAbility
-abilityManager_ : sptr<IInputMethodSystemAbility>
-imeListener_ : shared_ptr<InputMethodEngineListener>
-kdListener_ : shared_ptr<KeyboardListener>
-panels_ : ConcurrentMap
+GetInstance() : InputMethodAbility&
+SetCoreAndAgent() : int32_t
+InsertText() : int32_t
+DeleteForward() : int32_t
+CreatePanel() : int32_t
+ShowPanel() : int32_t
InputMethodPanel
-window_ : sptr<Window>
-panelType_ : PanelType
-panelFlag_ : PanelFlag
-windowId_ : uint32_t
+CreatePanel() : int32_t
+DestroyPanel() : int32_t
+ShowPanel() : int32_t
+HidePanel() : int32_t
+Resize() : int32_t
+MoveTo() : int32_t

2.4 模块内部依赖框图

Service Layer
Framework Layer
IPC
IPC
IPC
InputMethodSystemAbility Module
InputMethodSystemAbility
UserSessionManager
ImeInfoInquirer
PerUserSession
ClientGroup
ImeData
ImeStateManager
ImeCfgManager
FullImeInfoManager
InputMethodAbility Module
InputMethodAbility
InputCoreImpl
InputAgentImpl
InputMethodPanel
InputMethodController Module
InputMethodController
InputClientImpl
DataChannelImpl
KeyEventHandler
Common Layer
global.h
message.h
block_queue.h
itypes_util.h


3. 模块间交互

3.1 交互描述

3.1.1 与外部模块的交互
外部模块 交互方式 说明
ability_runtime 依赖调用 用于启动输入法ExtensionAbility
window_manager 依赖调用 用于创建和管理软键盘窗口
ipc IPC通信 跨进程通信基础设施
samgr 服务注册 注册InputMethodSystemAbility服务
bundle_framework 依赖调用 查询输入法应用信息
common_event_service 事件订阅 订阅系统事件(用户切换、包安装等)
access_token 权限检查 验证调用者权限
input 键盘事件 处理物理键盘输入
os_account 用户管理 多用户场景支持
graphic_2d 图形渲染 软键盘UI渲染
3.1.2 IPC通信机制

输入法进程 服务进程 应用进程 输入法进程 服务进程 应用进程 IPC通信流程 IInputMethodSystemAbility (StartInput/ShowInput) IInputMethodCore (StartInput) SetCoreAndAgent 返回Agent代理 IInputMethodAgent (InsertText等) IInputDataChannel (GetTextBeforeCursor)

3.1.3 异步处理与事件驱动
  1. 消息队列机制

    • 使用BlockQueue实现异步消息传递
    • 支持超时等待和阻塞操作
  2. 事件处理器

    • 基于EventHandler实现异步任务调度
    • 支持延迟任务和优先级调度
  3. 事件监听

    • ImeEventListener:监听输入法状态变化
    • OnTextChangedListener:监听文本变化
    • PanelStatusListener:监听面板状态变化
3.1.4 多线程处理
cpp 复制代码
// 工作线程
std::thread workThreadHandler;  // 消息处理线程

// 线程安全机制
std::mutex abilityLock_;        // 服务代理锁
std::mutex agentLock_;          // Agent锁
std::recursive_mutex clientInfoLock_;  // 客户端信息锁
std::mutex textConfigLock_;     // 文本配置锁

// 原子操作
std::atomic_bool isEditable_;   // 可编辑状态
std::atomic_bool isBound_;      // 绑定状态

3.2 外部依赖框图

基础依赖
graphic_2d

图形渲染/显示管理
hilog

日志记录/调试追踪
系统依赖
window_manager

窗口创建/管理/键盘面板
os_account

多用户支持/用户ID获取
input

键盘事件处理/按键分发
功能依赖
bundle_framework

包信息查询/应用安装状态
common_event_service

系统事件订阅/用户切换事件
access_token

权限检查/身份验证
核心依赖
ability_runtime

ExtAbility/Context
samgr

SystemAbility注册/发现
ipc

IPC通信/Proxy/Stub
InputMethod IMF
InputMethodSystemAbility
InputMethodController
InputMethodAbility


4. 状态机转换图

4.1 状态机模型

4.1.1 IME状态机

输入法引擎(IME)的生命周期由三个主要状态组成:

cpp 复制代码
enum class ImeStatus : uint32_t { 
    STARTING,   // 正在启动
    READY,      // 就绪
    EXITING     // 正在退出
};

enum class ImeEvent : uint32_t {
    START_IME,           // 启动IME
    START_IME_TIMEOUT,   // 启动超时
    STOP_IME,            // 停止IME
    SET_CORE_AND_AGENT,  // 设置Core和Agent
};

enum class ImeAction : uint32_t {
    DO_NOTHING,
    HANDLE_STARTING_IME,
    FORCE_STOP_IME,
    STOP_READY_IME,
    START_AFTER_FORCE_STOP,
    DO_SET_CORE_AND_AGENT,
    DO_ACTION_IN_NULL_IME_DATA,
    DO_ACTION_IN_IME_EVENT_CONVERT_FAILED,
};

4.2 状态机树图

IME States

Root
STARTING

正在启动中
READY

就绪可用
EXITING

正在退出
等待IME连接

超时检测
处理输入请求

响应用户操作
等待IME停止

清理资源

4.3 状态机切换规则

状态转换表
当前状态 触发事件 目标状态 执行动作
READY START_IME READY DO_NOTHING
STARTING START_IME STARTING HANDLE_STARTING_IME
EXITING START_IME EXITING START_AFTER_FORCE_STOP
READY START_IME_TIMEOUT READY DO_NOTHING
STARTING START_IME_TIMEOUT EXITING START_AFTER_FORCE_STOP
EXITING START_IME_TIMEOUT EXITING START_AFTER_FORCE_STOP
READY STOP_IME EXITING STOP_READY_IME
STARTING STOP_IME EXITING FORCE_STOP_IME
EXITING STOP_IME EXITING FORCE_STOP_IME
READY SET_CORE_AND_AGENT READY DO_NOTHING
STARTING SET_CORE_AND_AGENT READY DO_SET_CORE_AND_AGENT
EXITING SET_CORE_AND_AGENT EXITING DO_NOTHING
状态转换代码定义
cpp 复制代码
static inline const std::map<std::pair<ImeStatus, ImeEvent>, 
                            std::pair<ImeStatus, ImeAction>> imeEventConverter_ = {
    // READY状态的转换
    { { ImeStatus::READY, ImeEvent::START_IME }, 
      { ImeStatus::READY, ImeAction::DO_NOTHING } },
    { { ImeStatus::READY, ImeEvent::START_IME_TIMEOUT }, 
      { ImeStatus::READY, ImeAction::DO_NOTHING } },
    { { ImeStatus::READY, ImeEvent::STOP_IME }, 
      { ImeStatus::EXITING, ImeAction::STOP_READY_IME } },
    { { ImeStatus::READY, ImeEvent::SET_CORE_AND_AGENT }, 
      { ImeStatus::READY, ImeAction::DO_NOTHING } },
    
    // STARTING状态的转换
    { { ImeStatus::STARTING, ImeEvent::START_IME }, 
      { ImeStatus::STARTING, ImeAction::HANDLE_STARTING_IME } },
    { { ImeStatus::STARTING, ImeEvent::START_IME_TIMEOUT },
      { ImeStatus::EXITING, ImeAction::START_AFTER_FORCE_STOP } },
    { { ImeStatus::STARTING, ImeEvent::STOP_IME }, 
      { ImeStatus::EXITING, ImeAction::FORCE_STOP_IME } },
    { { ImeStatus::STARTING, ImeEvent::SET_CORE_AND_AGENT },
      { ImeStatus::READY, ImeAction::DO_SET_CORE_AND_AGENT } },
    
    // EXITING状态的转换
    { { ImeStatus::EXITING, ImeEvent::START_IME }, 
      { ImeStatus::EXITING, ImeAction::START_AFTER_FORCE_STOP } },
    { { ImeStatus::EXITING, ImeEvent::START_IME_TIMEOUT },
      { ImeStatus::EXITING, ImeAction::START_AFTER_FORCE_STOP } },
    { { ImeStatus::EXITING, ImeEvent::STOP_IME }, 
      { ImeStatus::EXITING, ImeAction::FORCE_STOP_IME } },
    { { ImeStatus::EXITING, ImeEvent::SET_CORE_AND_AGENT }, 
      { ImeStatus::EXITING, ImeAction::DO_NOTHING } }
};

4.4 状态机转换图

START_IME

(启动请求)
SET_CORE_AND_AGENT

(成功连接)
START_IME_TIMEOUT

(启动超时)
STOP_IME

(停止请求)
START_IME

(重复启动)
SET_CORE_AND_AGENT

(已连接)
STOP_IME

(停止请求)
START_IME_TIMEOUT

(超时重启)
FORCE_STOP完成
STARTING
READY
EXITING
等待IME连接

超时时间: 8秒
处理输入请求

响应用户操作
清理资源

等待停止完成

4.5 客户端状态机

Attach()

绑定成功
Close()

或 失焦
INACTIVE
ACTIVE
客户端未与输入法服务绑定

  • 不能进行文本输入

  • 等待Attach调用
    客户端已与输入法服务绑定

  • 可以进行文本输入

  • 可以显示/隐藏软键盘

  • 可以接收输入法的回调

4.6 状态转换触发条件

状态转换触发条件
START_IME

• 用户点击输入框

• 应用调用Attach()

• 系统启动默认输入法
SET_CORE_AND_AGENT

• IME成功启动并回调

• 建立Core和Agent连接
START_IME_TIMEOUT

• IME启动超时(8秒)

• 需要强制停止并重启
STOP_IME

• 用户切换输入法

• 应用调用Close()

• 系统要求停止


5. 接口设计

5.1 公共接口

5.1.1 InputMethodController API
接口名称 功能描述 参数 返回值
GetInstance() 获取单例实例 sptr<InputMethodController>
Attach() 绑定输入法 listener, isShowKeyboard, textConfig, type int32_t 错误码
Close() 关闭输入法 int32_t 错误码
ShowTextInput() 显示软键盘 type int32_t 错误码
HideTextInput() 隐藏软键盘 int32_t 错误码
ShowSoftKeyboard() 显示软键盘(需权限) type int32_t 错误码
HideSoftKeyboard() 隐藏软键盘(需权限) int32_t 错误码
OnCursorUpdate() 更新光标位置 cursorInfo int32_t 错误码
OnSelectionChange() 更新选择范围 text, start, end int32_t 错误码
SwitchInputMethod() 切换输入法 trigger, name, subName int32_t 错误码
ListInputMethod() 列出输入法 props int32_t 错误码
GetCurrentInputMethod() 获取当前输入法 shared_ptr<Property>
DispatchKeyEvent() 分发键盘事件 keyEvent, callback int32_t 错误码
SendPrivateCommand() 发送私有命令 privateCommand int32_t 错误码
SetPreviewText() 设置预览文本 text, range int32_t 错误码
FinishTextPreview() 完成文本预览 int32_t 错误码
5.1.2 InputMethodAbility API
接口名称 功能描述 参数 返回值
GetInstance() 获取单例实例 InputMethodAbility&
SetCoreAndAgent() 设置Core和Agent int32_t 错误码
InsertText() 插入文本 text, callback int32_t 错误码
DeleteForward() 向前删除 length, callback int32_t 错误码
DeleteBackward() 向后删除 length, callback int32_t 错误码
GetTextBeforeCursor() 获取光标前文本 number, text, callback int32_t 错误码
GetTextAfterCursor() 获取光标后文本 number, text, callback int32_t 错误码
MoveCursor() 移动光标 keyCode, callback int32_t 错误码
CreatePanel() 创建面板 context, panelInfo, panel int32_t 错误码
DestroyPanel() 销毁面板 panel int32_t 错误码
ShowPanel() 显示面板 panel int32_t 错误码
HidePanel() 隐藏面板 panel int32_t 错误码
HideKeyboardSelf() 隐藏自身键盘 int32_t 错误码
SetImeListener() 设置IME监听器 imeListener
SetKdListener() 设置键盘监听器 kdListener
IsCurrentIme() 是否当前输入法 bool
GetSecurityMode() 获取安全模式 security int32_t 错误码
5.1.3 错误码定义
cpp 复制代码
namespace ErrorCode {
enum {
    NO_ERROR = 0,                           // 成功
    ERROR_NULL_POINTER,                     // 空指针
    ERROR_BAD_PARAMETERS,                   // 参数错误
    ERROR_STATUS_PERMISSION_DENIED,         // 权限拒绝
    ERROR_PARAMETER_CHECK_FAILED,           // 参数检查失败
    ERROR_SERVICE_START_FAILED,             // 服务启动失败
    ERROR_CLIENT_NOT_EDITABLE,              // 客户端不可编辑
    ERROR_CLIENT_NOT_BOUND,                 // 客户端未绑定
    ERROR_IME_NOT_STARTED,                  // 输入法未启动
    ERROR_IME_NOT_FOUND,                    // 输入法未找到
    ERROR_TEXT_PREVIEW_NOT_SUPPORTED,       // 不支持文本预览
    ERROR_INVALID_PRIVATE_COMMAND_SIZE,     // 私有命令大小无效
    ERROR_INVALID_RANGE,                    // 范围无效
    // ...
};
}

5.2 数据交换接口

5.2.1 IDL接口定义

IInputMethodSystemAbility.idl

idl 复制代码
interface IInputMethodSystemAbility {
    ErrCode StartInput([in] InputClientInfoInner inputClientInfoInner, 
                       [out] IRemoteObject[] agents,
                       [out] BindImeInfo[] imeInfos);
    ErrCode ShowCurrentInput([in] unsigned int type);
    ErrCode HideCurrentInput();
    ErrCode ShowInput([in] IInputClient client, [in] unsigned int type);
    ErrCode HideInput([in] IInputClient client);
    ErrCode ReleaseInput([in] IInputClient client, [in] unsigned int sessionId);
    ErrCode SwitchInputMethod([in] String bundleName, 
                              [in] String subName, 
                              [in] unsigned int trigger);
    // ...
}

IInputMethodCore.idl

idl 复制代码
interface IInputMethodCore {
    int StartInput([in] InputClientInfo clientInfo, [in] boolean isBindFromClient);
    int StopInput([in] IRemoteObject channel, [in] unsigned int sessionId);
    int ShowKeyboard([in] int requestKeyboardReason);
    int HideKeyboard();
    void OnSetSubtype([in] SubProperty subProperty);
    // ...
}

IInputMethodAgent.idl

idl 复制代码
interface IInputMethodAgent {
    void OnCursorUpdate([in] int positionX, [in] int positionY, [in] int height);
    void OnSelectionChange([in] String text, [in] int oldBegin, 
                           [in] int oldEnd, [in] int newBegin, [in] int newEnd);
    void OnAttributeChange([in] InputAttributeInner attribute);
    int DispatchKeyEvent([in] KeyEventValue keyEvent, 
                         [in] unsigned long cbId, 
                         [in] IRemoteObject channel);
    int SendPrivateCommand([in] Value value);
    // ...
}

5.3 接口调用时序图

5.3.1 应用绑定输入法时序

InputMethodAbility InputMethodSystemAbility InputMethodController App InputMethodAbility InputMethodSystemAbility InputMethodController App 1. Attach(listener, textConfig) 2. StartInput(clientInfo) 3. StartCurrentIme() 4. SetCoreAndAgent() 5. Return(agents, imeInfos) 6. SetAgent(agent) 7. Return NO_ERROR 8. StartInput(clientInfo) 9. ShowKeyboard()

5.3.2 文本输入时序

InputMethodAbility InputMethodController App InputMethodAbility InputMethodController App 1. InsertText("hello") 2. InsertText("hello") (IInputDataChannel) 3. OnTextChangedListener ::InsertText("hello") 4. 更新UI显示 5. OnSelectionChange() (IInputMethodAgent)

5.3.3 输入法切换时序

NewIME OldIME InputMethodSystemAbility InputMethodController App NewIME OldIME InputMethodSystemAbility InputMethodController App 1. SwitchInputMethod(bundleName) 2. SwitchInputMethod() 3. StopInput() 4. HideKeyboard() 5. StopCurrentIme() 6. StartIme(newIme) 7. SetCoreAndAgent() 8. StartInput() 9. ShowKeyboard() 10. NotifyImeChange() 11. Return


附录

A. 术语表

术语 全称 说明
IMF Input Method Framework 输入法框架
IMC Input Method Controller 输入法控制器(应用侧)
IMA Input Method Ability 输入法能力(输入法侧)
IMSA Input Method System Ability 输入法系统服务
IME Input Method Engine 输入法引擎
SA System Ability 系统能力
IPC Inter-Process Communication 进程间通信
IDL Interface Definition Language 接口定义语言
相关推荐
Trouvaille ~4 小时前
【Linux】UDP Socket编程实战(二):网络字典与回调设计
linux·运维·服务器·网络·c++·udp·操作系统
凉、介4 小时前
静态路由探究
网络·笔记·操作系统·嵌入式
ujainu7 小时前
Flutter + OpenHarmony 实战:构建清晰、健壮的三屏状态流转
flutter·游戏·openharmony
ujainu8 小时前
Flutter + OpenHarmony 实战:构建独立可复用的皮肤选择界面
flutter·游戏·openharmony
_OP_CHEN8 小时前
【Linux系统编程】(二十六)一文吃透 Ext 系列文件系统软硬链接:原理、实战与底层逻辑揭秘
linux·操作系统·文件系统·c/c++·硬链接·软链接·ext2文件系统
fleaxin9 小时前
统信服务器操作系统V20(1070)安装过程
docker·操作系统·nvidia·统信
ujainu20 小时前
Flutter + OpenHarmony 游戏开发进阶:主菜单架构与历史最高分持久化
flutter·游戏·架构·openharmony
Goway_Hui21 小时前
【开源鸿蒙跨平台开发--KuiklyUI--07】详解:如何使用 Trae 开发 Kuikly-OH 跨端应用
开源·openharmony·kuikly
●VON1 天前
React Native for OpenHarmony:贪吃蛇游戏的开发与跨平台适配实践
学习·react native·react.js·游戏·openharmony