AI全家桶代码合并
authorluozheng <1732036298@qq.com>
Fri, 29 Aug 2025 06:27:34 +0000 (14:27 +0800)
committerluozheng <1732036298@qq.com>
Fri, 29 Aug 2025 06:27:34 +0000 (14:27 +0800)
25 files changed:
code/sdk/application/wearable/fd230/nativeapp/CMakeLists.txt
code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceConnectingView.h
code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceModel.h
code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceModelC.h [new file with mode: 0644]
code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoicePresenter.h
code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceSelectView.h [new file with mode: 0644]
code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceView.h
code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceVolumeView.h [new file with mode: 0644]
code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/Aivoice4gServiceConView.h [new file with mode: 0644]
code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AivoiceChatContentListItemView.h
code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AivoiceListeningView.h
code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AivoiceReturnResultTextView.h
code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AivoiceThinkingView.h
code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceConnectingView.cpp
code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceModel.cpp
code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoicePresenter.cpp
code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceSelectView.cpp [new file with mode: 0644]
code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceView.cpp
code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceVolumeView.cpp [new file with mode: 0644]
code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/Aivoice4gServiceConView.cpp [new file with mode: 0644]
code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AivoiceChatContentListItemView.cpp
code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AivoiceListeningView.cpp
code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AivoiceReturnResultTextView.cpp
code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AivoiceThinkingView.cpp
code/sdk/zhihui/ai/include/cat1_ws.h

index 55059fc..76dac27 100644 (file)
@@ -75,6 +75,7 @@ set(PRIVATE_HEADER
     ${ROOT_DIR}/zhihui/4g/cat1Service
     ${ROOT_DIR}/zhihui/4g/cat1Service/include
     ${ROOT_DIR}/zhihui/4g/cat1Service/Service
+    ${ROOT_DIR}/zhihui/ai/include/
 
 )
 
index 4f69a4e..2042f7f 100644 (file)
@@ -80,7 +80,6 @@ namespace OHOS
         UIButton *cancelButton{nullptr};
         UIImageAnimatorView *connectingAnimatorView{nullptr};
         ImageAnimatorInfo connectingImageInfo[AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES];
-        const ImageInfo **connectingPathsArray{nullptr};
     };
 }
 
index f45155f..529c518 100644 (file)
 #define AIAUDIO_TYPE_SBC 1
 #define AIAUDIO_TYPE_MSBC 2
 
+#define AI_VOICE_ENABLE 0
+
 // 设置当前使用的音频类型,0 表示 PCM,1 表示 SBC,2 表示 MSBC
 #define CURRENT_AIAUDIO_TYPE AIAUDIO_TYPE_SBC
 
+#if defined(SUPPORT_CHINA_MOBILE_DMP) || defined(SUPPORT_CHINA_MOBILE_AI_REGULATION)
+    #define AI_VOICE_FD230  // 九天版本
+#elif defined(BOARD_N9)
+    #define AI_VOICE_N9 //N9 星辰Ai
+#else
+    #define AI_VOICE_FD230   
+#endif
+
+
 namespace OHOS
 {
+#define AI_SELECT_DEFAULT -1
+#define AI_SELECT_4G  1
+#define AI_SELECT_BT 0
 
     class AiVoiceModel
     {
@@ -48,8 +62,6 @@ namespace OHOS
         void DeleteLocalOpenAIAPIKeys();
         bool GetAPPBluetoothIsConnect(void);
         bool GetMobileDataIsOpen(void);
-        bool GetAiVoiceConnectStatus(void);
-        void SetAiVoiceConnectStatus(bool state);
         void QuerySelectedAiModelIsConnect();
         void CancelCurAIChat(void);
         int GetAIResponseType(void);
@@ -64,6 +76,7 @@ namespace OHOS
         bool AddAiAnswerToChatItems();
         bool AddChatContentToItemArray(const ChatContentItem &item);
         uint8_t GetChatContentListCount(void);
+        void SetChatContentListCount(uint8_t count);
 
         // 更新和清空问题及回答
         bool RemoveLastTwoItemsOrClear();
@@ -78,9 +91,8 @@ namespace OHOS
         void SetAiAnswerStrStr(std::string str);
         void SetAiAnswerStrStr(std::string str,uint8_t type);
         uint8_t GetCurUsingAiModelType(void);
+        uint8_t GetCurUsing4GAiModelType(void);
 
-        // 文件检查和AI状态管理
-        void CheckFileAndSendAIIsReady();
         //发送AI已经就绪(继续对话时候使用)
         void sendAIIsReady();
 
@@ -106,6 +118,18 @@ namespace OHOS
         void start_ai_isready_timer(uint32_t interval = 1000);
         void stop_ai_isready_timer(void);
 
+        void start_ai4g_connect_timer(uint32_t interval = 1000);
+        void stop_ai4g_connect_timer(void);
+
+        void start_ai4g_tts_play_timer(uint32_t interval = 600);
+        void stop_ai4g_tts_play_timer(void);
+
+        void start_update_ai_answer_timer(uint32_t interval = 300);
+        void stop_update_ai_answer_timer(void);
+
+        void start_uapi_stop_tts_timer(uint32_t interval = 2000);
+        void stop_uapi_stop_tts_timer(void);
+
         void SetSelectAiModel(int index);
         int GetSelectAiModel(void);
         int GetAiModelTextId(void);
@@ -118,6 +142,29 @@ namespace OHOS
         void SetIsLimitDisplayed(bool value);
         bool GetIsLimitDisplayed(void);
 
+        void SetAI_4G_state(bool state);
+        bool GetAI_4G_state(void);
+        void SetAI_BT_state(bool state);
+        bool GetAI_BT_state(void);
+        void SetInit_4gai_task(bool state);
+        bool GetInit_4gai_task(void);
+        void SetSelect4gorbt(int state);
+        int GetSelect4gorbt(void);
+        
+        void cancel_tts_play(void);
+
+        void ProcessTextByPunctuation();
+        std::string GetAccumulatedText(void);
+        void sendSegment(const std::string &text, size_t pos);
+
+        bool is_need_to_jump_result_view(void);
+
+        bool getentryTextViewState(void);
+
+        bool get_is_first_receive();
+        void set_is_first_receive(bool);
+        void delete_start_line_break_str(std::string &str);
+
     private:
         AiVoiceModel();
         ~AiVoiceModel();
@@ -134,6 +181,7 @@ namespace OHOS
 #endif
         std::string userQuestionStr;                                         // 用户提出的问题
         std::string aiAnswerStr;                                             // AI回答的问题
+        std::string accumulatedText;                                         // tts播放文本
         uint8_t ChatContentListCount{0};                                     // 列表数量
         static const uint16_t MaxChatContentListCount = 2;                   // 对话列表最大数量
         ChatContentItem chatTtems[MaxChatContentListCount] = {0, "", false}; // 对话项数组
@@ -145,6 +193,14 @@ namespace OHOS
         int16_t curView{0};
         bool isClickable{false};
         bool isLimitDisplayed{false};//AI答案是否显示到极限了
+
+        bool AI_4G_state{false};             //4g网络状态
+        bool AI_BT_state{false};             //蓝牙连接状态
+        bool init_4gai_task{false};          //4g服务器连接状态
+        uint8_t select4gorbt{-1};           //0:4g 1:蓝牙 -1:未连接
+
+        bool isFirstReceive{true};        //静态变量标记是否是首次接收
+        bool hasTtsStartSucceeded{false}; // uapi_start_tts 成功后置位,仅允许发送一次
     };
 
 }
diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceModelC.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceModelC.h
new file mode 100644 (file)
index 0000000..c74b0be
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef AI_VOICE_MODELC_H
+#define AI_VOICE_MODELC_H
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C"
+{
+#endif
+#endif
+#include <stdint.h>
+
+    uint8_t getselect4gorbtai(void);
+    uint8_t get_clear_queue_stream(void);
+    void set_clear_queue_stream(uint8_t);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif
+#endif
\ No newline at end of file
index d432da2..f351927 100644 (file)
@@ -13,6 +13,7 @@
 #include "View.h"
 #include "ui_resource_string.h"
 #include "components/ui_time_picker.h"
+#include "components/ui_slider.h"
 #include "ModelListenerSample.h"
 namespace OHOS
 {
@@ -23,8 +24,9 @@ namespace OHOS
                              public UIView::OnDragListener,
                              public RootView::OnKeyActListener,
                              public UIPicker::SelectedListener,
-                             public UIView::OnTouchListener,
-                             public ModelListenerSample
+                             public UIView::OnRotateListener,
+                             public UIView::OnTouchListener
+                            //  public ModelListenerSample
     {
     public:
         typedef enum : uint8_t
@@ -33,7 +35,7 @@ namespace OHOS
             AIMODES_KIMI,            /*KIMI*/
             AIMODES_DOUBAO,          /*豆包*/
             AIMODES_TONGYI_QIANWEN,  /*通义千问->DeepSeek*/
-            AIMODES_IFLYTEK_SPARK,   /*讯飞星火->lingxi*/
+            AIMODES_IFLYTEK_SPARK,   /*讯飞星火*/
             AIMODES_CHATGPT,         /*chatgpt*/
             AIMODES_MAX_NUM,
         } aimodels;
@@ -42,10 +44,8 @@ namespace OHOS
         static AiVoicePresenter *GetInstance();
 
         void OnStart() override;
-        void OnResume() override;
-        void OnPause() override;
         void OnStop() override;
-        void Notify() override;
+        // void Notify() override;
         void calculateChatContentItemViewHeight(std::string text, bool flag);
 
         bool JumpToReturnResultTextView(void);
@@ -55,6 +55,8 @@ namespace OHOS
         void FunctionKeyOnClickToChangeAIModel(void);
         void DragLeftToRightChangeAIModel(void);
         void DragRightToLetfChangeAIModel(void);
+        void ChangeVolume(UIView &view, const RotateEvent &event);
+        void JumpThinkingView(void);
 
     private:
         bool OnClick(UIView &view, const ClickEvent &event) override;
@@ -64,6 +66,8 @@ namespace OHOS
         bool OnDragEnd(UIView &view, const DragEvent &event) override;
         bool OnKeyAct(UIView &view, const KeyEvent &event) override; // 增加按键事件
         void OnPickerStoped(UIPicker &picker) override;
+        bool OnRotate(UIView& view, const RotateEvent& event);
+        bool OnRotateEnd(UIView& view, const RotateEvent& event);
 
         AiVoiceModel *model;
         bool X_DRAG_FLAG{false};
diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceSelectView.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceSelectView.h
new file mode 100644 (file)
index 0000000..a920a21
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef AIVOICESELECTVIEW_H
+#define AIVOICESELECTVIEW_H
+#include "components/ui_scroll_view.h"
+#include "components/ui_label_ext.h"
+#include "components/ui_button.h"
+
+namespace OHOS
+{
+    static constexpr const char *AIVOICE_SELECT_VIEW_BUTTON4G_VIEW_ID = "aivoice_select_view_button4g_view_id"; // 选择界面4G连接按钮
+    static constexpr const char *AIVOICE_SELECT_VIEW_BUTTONBT_VIEW_ID = "aivoice_select_view_buttonbt_view_id"; // 选择界面蓝牙连接按钮
+
+    class AiVoiceSelectView
+    {
+    public:
+        AiVoiceSelectView();
+        ~AiVoiceSelectView();
+        static AiVoiceSelectView *GetInstance(void);
+        UIScrollView *CreateAiVoiceSelectView(void);
+
+    private:
+        void ClearAll(void);
+        UILabelExt *title{nullptr};
+        UIScrollView *scrollView{nullptr};
+        UILabelExt *label4g{nullptr};
+        UILabelExt *labelbt{nullptr};
+        UIButton *button4g{nullptr};
+        UIButton *buttonbt{nullptr};
+    };
+}
+
+#endif
\ No newline at end of file
index fc65f55..48c5cb6 100644 (file)
@@ -15,6 +15,7 @@
 #include "components/ui_scroll_view.h"
 #include "components/ui_image_view.h"
 #include "components/ui_picker.h"
+#include "components/ui_slider.h"
 #include "aivoice/include/AiVoiceBluetoothFailedStartView.h"
 #include "aivoice/include/AivoiceMobileDataFailedStartView.h"
 #include "aivoice/include/AivoiceConnectTimeoutView.h"
@@ -25,6 +26,9 @@
 #include "aivoice/include/apikeys/NotSetApiKeysView.h"
 #include "aivoice/include/apikeys/ApiKeysDeleteView.h"
 #include "aivoice/include/AiVoiceConnectingView.h"
+#include "aivoice/include/AiVoiceSelectView.h"
+#include "aivoice/include/Aivoice4gServiceConView.h"
+#include "aivoice/include/AiVoiceVolumeView.h"
 #include "ui_resource_string.h"
 #include "iostream"
 #include "string"
@@ -39,7 +43,7 @@ namespace OHOS
     static constexpr const char *AIMODEL_TONGYI_QIANWEN_PATH = "/user/res/AIVoice/aimodels/aimodes_tongyi_qianwen.bin"; /*通义千问*/
     static constexpr const char *AIMODEL_IFLYTEK_SPARK_PATH = "/user/res/AIVoice/aimodels/aimodes_iflytek_spark.bin";   /*讯飞星火*/
     static constexpr const char *AIMODEL_DEEPSEEK_PATH = "/user/res/AIVoice/aimodels/aimodes_deepseek.bin";             /*deepseek*/
-    static constexpr const char *AIMODEL_LINGXI_PATH = "/user/res/AIVoice/aimodels/aimodels_lingxi.bin";                /*lingxi*/
+    static constexpr const char *AIMODEL_LINGXI_PATH = "/user/res/AIVoice/aimodels/aimodels_lingxi.bin";                /*jiutian*/
 
     /*组件ID*/
     static constexpr const char *AIVOICE_START_CHAT_BUTTON_VIEW_ID = "aivoice_start_chat_button_view_id"; // 开始对话
@@ -61,6 +65,9 @@ namespace OHOS
         AIVOICE_NOTSETAPIKEYS,                           // API Keys notset界面
         AIVOICE_APIKEYS_DELETE,                          // API Keys 删除界面
         AIVOICE_AIMODE_CONNECTING,                       // AI Mode正在连接视图
+        AIVOICE_SELECT_VIEW,                             // AI选择界面
+        AIVOICE_4GSERVICECON_VIEW,                       // AI4G连接中界面
+        AIVOICE_VOLUME_VIEW,                            // AI音量界面
         MAX_AIVOICE_VIEWID,
     } AIVOICEVIEWID;
 
@@ -70,9 +77,9 @@ namespace OHOS
         {STR_AIMODELS_DOUBAO, AIMODEL_DOUBAO_PATH},
         // {STR_TONGYI_QIANWEN, AIMODEL_TONGYI_QIANWEN_PATH},
         {STR_DEEPSEEK, AIMODEL_DEEPSEEK_PATH},
-        // {STR_IFLYTEK_SPARK, AIMODEL_IFLYTEK_SPARK_PATH},
-        {STR_AIMODES_LINGXI, AIMODEL_LINGXI_PATH},
+        {STR_IFLYTEK_SPARK, AIMODEL_IFLYTEK_SPARK_PATH},
         {STR_AIMODES_CHATGPT, AIMODEL_CHATGPT_ON_PATH},
+        {STR_JIUTIAN, AIMODEL_LINGXI_PATH},
     };
 
     class AiVoicePresenter;
@@ -129,6 +136,9 @@ namespace OHOS
         bool ChangeAiVoicNotSetApiKeysView(int16_t thisView);
         bool ChangeAiVoicApiKeysDeleteView(int16_t thisView);
         bool ChangeAiVoicConnectingView(int16_t thisView);
+        bool ChangeAiVoicSelectView(int16_t thisView);
+        bool ChangeAiVoic4gServiceConView(int16_t thisView);
+        bool ChangeAiVoicVolumeView(int16_t thisView);
 
         void SetAiVoiceViewAllComponentsVisibilityStatus();
         void ChangeAiModelAndUpdateComponentsStatus(void);
@@ -147,6 +157,9 @@ namespace OHOS
         NotSetApiKeysView *p_NotSetApiKeysView{nullptr};
         ApiKeysDeleteView *p_ApiKeysDeleteView{nullptr};
         AiVoiceConnectingView *p_AiVoiceConnectingView{nullptr};
+        AiVoiceSelectView *p_AiVoiceSelectView{nullptr};
+        AiVoice4gServiceConView *p_Aivoice4gServiceConView{nullptr};
+        AiVoiceVolumeView *p_AiVoiceVolumeView{nullptr};
 
     private:
         UILabelExt *AiVoiceViewLabelInit(LabelConfig &labelconfig);
@@ -157,9 +170,12 @@ namespace OHOS
         bool CreateAiVoiceViewButton(void);
         bool CreateAiVoiceViewPicker(void);
         bool CreateAiVoiceScrollView(void);
-        void CreateAiVoiceView(void);
+        bool CreateAiVoiceVoiceView(void);
+        UIScrollView *CreateAiVoiceView(void);
+        void ClearAllAiVoiceScrollView(void);
         void ClearAll(void);
         void SetComponentVisibility(UIView *component, bool isVisible);
+        UIScrollView *scrollView{nullptr};
         UILabelExt *title{nullptr};          /*标题*/
         UILabelExt *startChatLabel{nullptr}; /*开始对话标签,暂时不用*/
         UIButton *startChatButton{nullptr};  /*开始对话按钮*/
@@ -172,7 +188,9 @@ namespace OHOS
         UIButton *apiKeysButton{nullptr};    /*API Keys按钮,,暂时不用*/
         UIPicker *aiModelPicker{nullptr};    /*ai模型选择器*/
         UIScrollView *AiVoiceScrollView[MAX_AIVOICE_VIEWID]{nullptr};
-        bool viewInitStatus{false};
+        /* ----------------------------------- 九天 ----------------------------------- */
+        UISlider *VolumeProcess{nullptr};
+        /* -------------------------------------------------------------------------- */
     };
 }
 #endif
\ No newline at end of file
diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceVolumeView.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/AiVoiceVolumeView.h
new file mode 100644 (file)
index 0000000..b52aa2a
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef AIVOICEVOLUMEVIEW_H
+#define AIVOICEVOLUMEVIEW_H
+
+#include "components/ui_scroll_view.h"
+#include "soundandvibration/include/SoundAndVibrationVolumeSettingView.h"
+namespace OHOS
+{
+    class AiVoiceVolumeView
+    {
+    public:
+        AiVoiceVolumeView();
+        ~AiVoiceVolumeView();
+        static AiVoiceVolumeView *GetInstance(void);
+        UIScrollView *CreateAiVoiceVolumeView(void);
+        void SetRequestFocus();
+
+    private:
+        void ClearAll();
+        UIScrollView *SystemVolumeScrollView{nullptr};
+        SoundAndVibrationVolumeSettingView *p_SoundAndVibrationVolumeSettingView{nullptr};
+    };
+}
+#endif
\ No newline at end of file
diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/Aivoice4gServiceConView.h b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/include/Aivoice4gServiceConView.h
new file mode 100644 (file)
index 0000000..495e68a
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef AIVOICE4GSERVICECONVIEW_H
+#define AIVOICE4GSERVICECONVIEW_H
+#include "components/ui_scroll_view.h"
+#include "components/ui_label_ext.h"
+#include "components/ui_button.h"
+#include "components/ui_image_animator.h"
+
+namespace OHOS
+{
+    class AiVoice4gServiceConView
+    {
+    public:
+        AiVoice4gServiceConView();
+        ~AiVoice4gServiceConView();
+        static AiVoice4gServiceConView *GetInstance(void);
+        UIScrollView *CreateAiVoice4gServiceConView(void);
+
+    private:
+        void ClearAll(void);
+        UIScrollView *scrollView{nullptr};
+        UILabelExt *label{nullptr};
+        UIImageAnimatorView *AI4GImageAni{nullptr};
+        ImageAnimatorInfo AI4GsearchImageInfo[8];
+    };
+}
+#endif
\ No newline at end of file
index 0897ec9..bde48ec 100644 (file)
@@ -29,6 +29,7 @@ namespace OHOS
 
     private:
         UILabel chatContentLabel;
+        UILabel mindLabel;
         UIImageView chatContentImage;
         UIScrollView chatContentScrollView;
         int m_viewHeight;
index d681965..c620e77 100644 (file)
@@ -71,6 +71,7 @@ namespace OHOS
         static AivoiceListeningView *GetInstance(void);
         UIScrollView *CreateAivoiceListeningView(void);
         UILabelExt *GetShowtimeoutLabel(void);
+        void StartOrStopAivoiceListeningImageAnimatorView(bool val);
 
     private:
         void ClearAll(void);
@@ -87,7 +88,6 @@ namespace OHOS
         UIButton *finishSpeakButton{nullptr};
         UIImageAnimatorView *AiVoiceListeningImageAnimatorView{nullptr};
         ImageAnimatorInfo AiVoiceListeningImageInfo[AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES];
-        const ImageInfo **AiVoiceListeningPathsArray{nullptr};
         UILabelExt *showtimeout{nullptr};
     };
 }
index 27d9e34..f3d8408 100644 (file)
@@ -60,6 +60,7 @@ namespace OHOS
         UIList *GetChatContentList(void);
         void UpdateTitleTextId(int textId);
         void IsScrollChatContentList(bool isScroll);
+        void SetRequestFocus();
 
     private:
         void ClearAll(void);
index d5b7c34..9bfdd78 100644 (file)
@@ -64,6 +64,7 @@ namespace OHOS
         ~AivoiceThinkingView();
         static AivoiceThinkingView *GetInstance(void);
         UIScrollView *CreateAivoiceThinkingView(void);
+        void StartOrStopAiVoiceThinkingImageAnimatorView(bool val);
 
     private:
         void ClearAll(void);
@@ -80,7 +81,6 @@ namespace OHOS
         UIButton *cancelThinkButton{nullptr};
         UIImageAnimatorView *AiVoiceThinkingImageAnimatorView{nullptr};
         ImageAnimatorInfo AiVoiceThinkingImageInfo[AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES];
-        const ImageInfo **AiVoiceThinkingPathsArray{nullptr};
     };
 }
 #endif
index 98b314e..542b308 100644 (file)
@@ -21,6 +21,69 @@ namespace OHOS
     static constexpr int16_t AIVOICE_CONNECTING_IMAGE_ANIMATOR_DELAY = 50; // 图片更新间隔
     static constexpr const char *AIVoiceListeningImagePaths = "/user/res/connect/";
 
+    const char *connecting_path_array[] = {
+        "/user/res/connect/1.bin",
+        "/user/res/connect/2.bin",
+        "/user/res/connect/3.bin",
+        "/user/res/connect/4.bin",
+        "/user/res/connect/5.bin",
+        "/user/res/connect/6.bin",
+        "/user/res/connect/7.bin",
+        "/user/res/connect/8.bin",
+        "/user/res/connect/9.bin",
+        "/user/res/connect/10.bin",
+        "/user/res/connect/11.bin",
+        "/user/res/connect/12.bin",
+        "/user/res/connect/13.bin",
+        "/user/res/connect/14.bin",
+        "/user/res/connect/15.bin",
+        "/user/res/connect/16.bin",
+        "/user/res/connect/17.bin",
+        "/user/res/connect/18.bin",
+        "/user/res/connect/19.bin",
+        "/user/res/connect/20.bin",
+        "/user/res/connect/21.bin",
+        "/user/res/connect/22.bin",
+        "/user/res/connect/23.bin",
+        "/user/res/connect/24.bin",
+        "/user/res/connect/25.bin",
+        "/user/res/connect/26.bin",
+        "/user/res/connect/27.bin",
+        "/user/res/connect/28.bin",
+        "/user/res/connect/29.bin",
+        "/user/res/connect/30.bin",
+        "/user/res/connect/31.bin",
+        "/user/res/connect/32.bin",
+        "/user/res/connect/33.bin",
+        "/user/res/connect/34.bin",
+        "/user/res/connect/35.bin",
+        "/user/res/connect/36.bin",
+        "/user/res/connect/37.bin",
+        "/user/res/connect/38.bin",
+        "/user/res/connect/39.bin",
+        "/user/res/connect/40.bin",
+        "/user/res/connect/41.bin",
+        "/user/res/connect/42.bin",
+        "/user/res/connect/43.bin",
+        "/user/res/connect/44.bin",
+        "/user/res/connect/45.bin",
+        "/user/res/connect/46.bin",
+        "/user/res/connect/47.bin",
+        "/user/res/connect/48.bin",
+        "/user/res/connect/49.bin",
+        "/user/res/connect/50.bin",
+        "/user/res/connect/51.bin",
+        "/user/res/connect/52.bin",
+        "/user/res/connect/53.bin",
+        "/user/res/connect/54.bin",
+        "/user/res/connect/55.bin",
+        "/user/res/connect/56.bin",
+        "/user/res/connect/57.bin",
+        "/user/res/connect/58.bin",
+        "/user/res/connect/59.bin",
+        "/user/res/connect/60.bin",
+    };
+
     static AiVoiceConnectingView *g_pAiVoiceConnecting{nullptr};
     AiVoiceConnectingView::AiVoiceConnectingView()
     {
@@ -50,7 +113,10 @@ namespace OHOS
                 connectingAnimatorView->Stop();
                 delete connectingAnimatorView;
                 connectingAnimatorView = nullptr;
-                FreeImageInfoArray(connectingPathsArray, AIVoiceListeningImagePaths, AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES);
+                for (int i = 0; i < AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES; i++)
+                {
+                    ImageCacheManager::GetInstance().UnloadSingleRes(connecting_path_array[i]);
+                }
             }
             if (cancelLabel)
             {
@@ -220,35 +286,31 @@ namespace OHOS
     bool AiVoiceConnectingView::CreateAivoiceConnectingImageAnimator(void)
     {
         WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceConnectingView::CreateAivoiceConnectingImageAnimator");
-        if (connectingPathsArray == nullptr)
-        {
-            connectingPathsArray = CreateImageInfoArray(AIVoiceListeningImagePaths, AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES);
-            if (connectingPathsArray == nullptr)
-            {
-                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceConnectingView::connectingPathsArray  is nullptr!!");
-                return false;
-            }
-        }
-
-        ImageAnimatorConfig imageanimatorconfig = {
-            .x = AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_X,
-            .y = AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_Y,
-            .width = AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_W,
-            .height = AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_H,
-            .imageInfoArray = connectingImageInfo,
-            .pathsArray = connectingPathsArray,
-            .numFrames = AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES,
-            .delay = AIVOICE_CONNECTING_IMAGE_ANIMATOR_DELAY,
-        };
         if (connectingAnimatorView == nullptr)
         {
-            connectingAnimatorView = connectingImageAnimatorInit(imageanimatorconfig);
+            connectingAnimatorView = new UIImageAnimatorView();
             if (connectingAnimatorView == nullptr)
             {
-                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceConnectingView::connectingAnimatorView new fail");
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceConnectingView::CreateAivoiceConnectingImageAnimator new connectingAnimatorView fail");
                 return false;
             }
         }
+        for (uint8_t i = 0; i < AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES; i++)
+        {
+            connectingImageInfo[i].imageInfo = ImageCacheManager::GetInstance().LoadSingleRes(connecting_path_array[i]);
+            connectingImageInfo[i].imageType = IMG_SRC_IMAGE_INFO;
+            connectingImageInfo[i].pos.x = AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_X;
+            connectingImageInfo[i].pos.y = AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_Y;
+            connectingImageInfo[i].width = AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_W;
+            connectingImageInfo[i].height = AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_H;
+        }
+        connectingAnimatorView->SetPosition(AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_X, AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_Y,
+                                            AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_W, AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_H);
+        connectingAnimatorView->SetImageAnimatorSrc(connectingImageInfo, AIVOICE_CONNECTING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES, AIVOICE_CONNECTING_IMAGE_ANIMATOR_DELAY);
+        connectingAnimatorView->SetRepeat(true);
+        connectingAnimatorView->SetAutoEnable(false);
+        connectingAnimatorView->SetResizeMode(UIImageView::FILL);
+        connectingAnimatorView->Start();
 
         return true;
     }
index 81676d5..9b3ec27 100644 (file)
@@ -6,6 +6,7 @@
  * @FilePath: /FD230/code/sdk/application/wearable/fd230app/nativeui/aivoice/src/AiVoiceModel.cpp
  */
 #include "aivoice/include/AiVoiceModel.h"
+#include "aivoice/include/AiVoiceModelC.h"
 #include "aivoice/include/AiVoicePresenter.h"
 #include "aivoice/include/AiVoiceView.h"
 #include "aivoice/include/AivoiceReturnResultTextView.h"
 #include <unistd.h>
 #include <sys/stat.h>
 #include <custom_save_runtime.h>
+#include "custom_runtime.h"
+#include "cat1_ws.h"
+#include "voice_call_volte_sample_wrapper.h"
+#include <los_base.h>
 namespace OHOS
 {
     // 声明定时器变量
@@ -150,38 +155,57 @@ namespace OHOS
     // 获取APP蓝牙是否已连接
     bool AiVoiceModel::GetAPPBluetoothIsConnect(void)
     {
-        // return SettingModel::GetInstance().GetPhoneConnectStatus();
-
-        #ifdef SUPPORT_BLE_SERVICE
+#ifdef SUPPORT_BLE_SERVICE
         return get_ble_connect();
-        #else
-        return false;   
-        #endif
+#else
+        return false;
+#endif
     }
 
     // 获取4G网络是否正常
     bool AiVoiceModel::GetMobileDataIsOpen(void)
     {
+        if (uapi_dev_runtime_get_cat1_networkstat() == 1)
+        {
+            return true;
+        }
         return false;
     }
 
     /*查询用户选择的AI模型是否已经连接*/
     void AiVoiceModel::QuerySelectedAiModelIsConnect()
     {
-        #ifdef SUPPORT_BLE_SERVICE
         auto it = selectAiModelToTextId.find(GetSelectAiModel());
         if (it != selectAiModelToTextId.end())
         {
             WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "[QuerySelectedAiModelIsConnect] SelectAiModel = %d", it->second.second);
-            inquire_AI_is_ready(it->second.second);
+            if (GetSelect4gorbt() == AI_SELECT_4G)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "GetSelect4gorbt() == AI_SELECT_4G");
+                if (GetInit_4gai_task())
+                {
+#if AI_VOICE_ENABLE
+                    uapi_UI_start_asr(GetCurUsing4GAiModelType());
+#endif
+                }
+                else
+                {
+                    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "init_4gai_task fail!!");
+                }
+            }
+            else if (GetSelect4gorbt() == AI_SELECT_BT)
+            {
+#ifdef SUPPORT_BLE_SERVICE
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "蓝牙:查询Ai是否就绪");
+                inquire_AI_is_ready(it->second.second);
+#endif
+            }
         }
-        #endif
     }
 
     // 获取当前正在使用的AI模型
     uint8_t AiVoiceModel::GetCurUsingAiModelType(void)
     {
-    
         auto it = selectAiModelToTextId.find(GetSelectAiModel());
         if (it != selectAiModelToTextId.end())
         {
@@ -190,13 +214,32 @@ namespace OHOS
         return 0;
     }
 
+    uint8_t AiVoiceModel::GetCurUsing4GAiModelType(void)
+    {
+#if AI_VOICE_ENABLE
+        int value = GetSelectAiModel();
+        std::map<int, std::pair<int, int>> selectAiModelToAiModelType = {
+            {0, {STR_DEEPSEEK, AI_TYPE_DE}},
+            {1, {STR_JIUTIAN, AI_TYPE_JIU}},
+            {2, {STR_AIMODELS_DOUBAO, AI_TYPE_DOU}},
+            {3, {STR_AIMODES_WENXINYIYAN, AI_TYPE_WEN}},
+            {4, {STR_AIMODES_KIMI, AI_TYPE_KIMI}},
+            {5, {STR_AIMODES_CHATGPT, AI_TYPE_0}},
+        };
+
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "GetCurUsing4GAiModelType = %d", selectAiModelToAiModelType[value].second);
+        return selectAiModelToAiModelType[value].second;
+#endif
+        return 0;
+    }
+
     /*取消当前AI对话*/
     void AiVoiceModel::CancelCurAIChat(void)
     {
-        // cancel_AI_cur_chat(); //线程发送取消当前对话
-        #ifdef SUPPORT_BLE_SERVICE
-        cancel_AI_cur_chat_();// 直接发送取消当前对话
-        #endif
+// cancel_AI_cur_chat(); //线程发送取消当前对话
+#ifdef SUPPORT_BLE_SERVICE
+        cancel_AI_cur_chat_(); // 直接发送取消当前对话
+#endif
     }
 
     int AiVoiceModel::GetAIResponseType(void)
@@ -232,6 +275,11 @@ namespace OHOS
         return ChatContentListCount;
     }
 
+    void AiVoiceModel::SetChatContentListCount(uint8_t count)
+    {
+        ChatContentListCount = count;
+    }
+
     /*添加聊天内容项到数组*/
     bool AiVoiceModel::AddChatContentToItemArray(const ChatContentItem &item)
     {
@@ -360,7 +408,7 @@ namespace OHOS
     {
         WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::UpdateUserQuestionStr");
 
-        if(!RemoveLastTwoItemsOrClear())
+        if (!RemoveLastTwoItemsOrClear())
         {
             return false;
         }
@@ -399,24 +447,6 @@ namespace OHOS
     bool AiVoiceModel::UpdateAiAnswerStr()
     {
         WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::UpdateAiAnswerStr");
-        #if 0
-        AiVoiceView *view_ = AiVoiceView::GetInstance();
-        if(view_!= nullptr )
-        {
-            if(view_->GetAiVoiceScrollView(AIVOICE_RETURN_RESULT_TEXT_VIEWID) && !view_->GetAiVoiceScrollView(AIVOICE_RETURN_RESULT_TEXT_VIEWID)->IsVisible())
-            {
-                return false;
-            }
-            else
-            {
-                if(!GetIsClickable())
-                {
-                    SetIsClickable(true);
-                }
-            }
-        }
-        #endif
-
         int index = GetChatContentListCount() - 1;
         if (index < 0 || index >= MaxChatContentListCount)
         {
@@ -455,7 +485,7 @@ namespace OHOS
             // 将更新后的 AI 回答内容添加到列表
             adapter->GetChatContentItem().push_back(chatTtems[GetChatContentListCount() - 1]);
             if (AiVoicePresenter::GetInstance())
-                AiVoicePresenter::GetInstance()->calculateChatContentItemViewHeight(chatTtems[GetChatContentListCount() - 1].text, true); 
+                AiVoicePresenter::GetInstance()->calculateChatContentItemViewHeight(chatTtems[GetChatContentListCount() - 1].text, true);
             p_AivoiceReturnResultTextView->GetChatContentList()->RefreshList();
         }
         else
@@ -471,7 +501,7 @@ namespace OHOS
     {
         isClickable = value;
     }
-    
+
     bool AiVoiceModel::GetIsClickable(void)
     {
         return isClickable;
@@ -497,22 +527,38 @@ namespace OHOS
     /*设置用户问题的字符串*/
     void AiVoiceModel::SetUserQuestionStr(std::string str)
     {
-        if (!entryTextViewState)
+        if (GetSelect4gorbt() == AI_SELECT_4G)
+        {
+            if (str.empty())
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "传入的问题为空");
+                return;
+            }
+            userQuestionStr += str;
+            if (!entryTextViewState)
+            {
+                SendMsgToUIService(UI_AI_JUMP_TO_RESULT_VIEW, 0, nullptr, 0);
+                entryTextViewState = true; // 进入返回结果界面的标志  避免重复发消息
+                usleep(50000);             // 延时等待创建完成,0.05秒
+            }
+            /* -------------------------------------------------------------------------- */
+            SendMsgToUIService(UI_UPDATE_USER_QUESTION_STR, 0, nullptr, 0);
+        }
+        else if (GetSelect4gorbt() == AI_SELECT_BT)
         {
-            #ifdef SUPPORT_BLE_SERVICE
-            SendMsgToUIService(UI_AI_JUMP_TO_RESULT_VIEW, 0, nullptr, 0);
-            #endif
-            entryTextViewState = true; // 进入返回结果界面的标志  避免重复发消息
-            usleep(50000);             // 延时等待创建完成,0.05秒
+            if (!entryTextViewState)
+            {
+                SendMsgToUIService(UI_AI_JUMP_TO_RESULT_VIEW, 0, nullptr, 0);
+                entryTextViewState = true; // 进入返回结果界面的标志  避免重复发消息
+                usleep(50000);             // 延时等待创建完成,0.05秒
+            }
+            /* -------------------------------------------------------------------------- */
+            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "传入的问题:%s", str.c_str());
+            userQuestionStr = str;
+            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "拼接的问题:%s", userQuestionStr.c_str());
+            /* -------------------------------------------------------------------------- */
+            SendMsgToUIService(UI_UPDATE_USER_QUESTION_STR, 0, nullptr, 0);
         }
-        /* -------------------------------------------------------------------------- */
-        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "传入的问题:%s",str.c_str());
-        userQuestionStr = str;
-        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "拼接的问题:%s",userQuestionStr.c_str());
-        /* -------------------------------------------------------------------------- */
-        #ifdef SUPPORT_BLE_SERVICE
-        SendMsgToUIService(UI_UPDATE_USER_QUESTION_STR, 0, nullptr, 0);
-        #endif
     }
 
     /*获取Ai回答的字符串*/
@@ -527,50 +573,330 @@ namespace OHOS
     void AiVoiceModel::SetAiAnswerStrStr(std::string str)
     {
         aiAnswerStr += str;
-        #ifdef SUPPORT_BLE_SERVICE
         SendMsgToUIService(UI_UPDATE_AI_ANSWER_STR, 0, nullptr, 0);
-        #endif
     }
 
-    void AiVoiceModel::SetAiAnswerStrStr(std::string str, uint8_t type)
+    // 安全替换 UTF-8 字符串中的字符
+    static void safe_replace_utf8(std::string &str, const std::string &from_chars, char replacement)
     {
-        AIResponseType = type;
-        errnote = str;
-        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AIResponseType = %d,errnote = %s\n", AIResponseType, errnote.c_str());
-        //如果是:AI录音解析错误或AI 回应错误 ,或者重传多次录音数据->跳转AI回应错误界面
-        if (AIResponseType == AiVoiceModel::AI_RECORDING_PARSING_ERROR || AIResponseType == AiVoiceModel::AI_RESPONSE_ERROR 
-            || AIResponseType == AiVoiceModel::AI_BLE_ERROR)
-        {
-            #ifdef SUPPORT_BLE_SERVICE
-            SendMsgToUIService(UI_AI_JUMP_TO_RESPONDERR_VIEW, 0, (void *)errnote.c_str(), errnote.length());
-            #endif
+        std::string result;
+        result.reserve(str.length()); // 预分配足够空间
+
+        const char *p = str.c_str();
+        const char *end = p + str.length();
+
+        while (p < end)
+        {
+            unsigned char c = *p;
+            size_t char_size = 1;
+
+            // 判断 UTF-8 字符的字节数
+            if ((c & 0x80) == 0)
+            {
+                // 1字节字符 (ASCII)
+                char_size = 1;
+            }
+            else if ((c & 0xE0) == 0xC0)
+            {
+                // 2字节字符
+                char_size = 2;
+            }
+            else if ((c & 0xF0) == 0xE0)
+            {
+                // 3字节字符 (常见中文)
+                char_size = 3;
+            }
+            else if ((c & 0xF8) == 0xF0)
+            {
+                // 4字节字符 (如 Emoji)
+                char_size = 4;
+            }
+            else
+            {
+                // 无效字符,按单字节处理
+                char_size = 1;
+            }
+
+            // 检查字符是否在要替换的集合中
+            bool replace = false;
+            if (char_size == 1)
+            {
+                // 单字节字符直接检查
+                replace = (from_chars.find(c) != std::string::npos);
+            }
+            else
+            {
+                // 多字节字符,提取完整字符并检查
+                std::string utf8_char(p, char_size);
+                for (size_t i = 0; i < from_chars.length();)
+                {
+                    // 提取 from_chars 中的下一个 UTF-8 字符
+                    unsigned char fc = from_chars[i];
+                    size_t fc_size = 1;
+
+                    if ((fc & 0x80) == 0)
+                    {
+                        fc_size = 1;
+                    }
+                    else if ((fc & 0xE0) == 0xC0)
+                    {
+                        fc_size = 2;
+                    }
+                    else if ((fc & 0xF0) == 0xE0)
+                    {
+                        fc_size = 3;
+                    }
+                    else if ((fc & 0xF8) == 0xF0)
+                    {
+                        fc_size = 4;
+                    }
+
+                    if (i + fc_size <= from_chars.length())
+                    {
+                        std::string fc_str = from_chars.substr(i, fc_size);
+                        if (fc_str == utf8_char)
+                        {
+                            replace = true;
+                            break;
+                        }
+                    }
+
+                    i += fc_size;
+                }
+            }
+
+            // 添加到结果字符串
+            if (replace)
+            {
+                result += replacement;
+            }
+            else
+            {
+                result.append(p, char_size);
+            }
+
+            p += char_size;
+        }
+
+        // 替换原字符串
+        str.swap(result);
+    }
+
+    static int fouce_count = 0; //
+    void AiVoiceModel::ProcessTextByPunctuation()
+    {
+        const std::string punctuation = ",。!?;:))“”、\"\""; // 要替换的中文标点
+        const char replacement = ',';                              // 替换为英文逗号
+        const size_t MAX_SEGMENT_LENGTH = 120;                     // 最大分段长度
+        const size_t MIN_SEGMENT_LENGTH = 1;                       // 最小发送长度(可调整)
+
+        if (accumulatedText.empty())
             return;
+
+        // 安全替换中文标点为英文逗号
+        std::string processedText = accumulatedText;
+        safe_replace_utf8(processedText, punctuation, replacement);
+
+        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "processedText:%s", processedText.c_str());
+
+        accumulatedText = processedText;
+        size_t commaPos = accumulatedText.find_last_of(',');
+
+        // 处理长度限制,若超过最大长度则强制分段
+        if (accumulatedText.length() >= MAX_SEGMENT_LENGTH)
+        {
+            commaPos = MAX_SEGMENT_LENGTH - 1;
+            // 查找最大长度内最近的逗号
+            size_t lastCommaInRange = accumulatedText.find_last_of(',', commaPos);
+            if (lastCommaInRange != std::string::npos)
+            {
+                commaPos = lastCommaInRange;
+            }
+        }
+
+        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "commaPos:%d", commaPos);
+
+        if (commaPos != std::string::npos)
+        {
+            // 按标点分段发送
+            sendSegment(accumulatedText, commaPos);
         }
-        else if (AiVoiceModel::AI_RESPONSE_END) // 如果是AI 回应结束
+        else
         {
-            if (errnote.empty()) // 如果没有回应数据
+            // 无逗号时的处理逻辑
+            if (accumulatedText.length() >= MIN_SEGMENT_LENGTH)
             {
-                WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::GetErrnote is empty!!");
-                AiVoiceModel::GetInstance().SetErrnote("响应内容为空");
-                std::string str = AiVoiceModel::GetInstance().GetErrnote();
-                #ifdef SUPPORT_BLE_SERVICE
-                SendMsgToUIService(UI_AI_JUMP_TO_RESPONDERR_VIEW, 0, (void *)str.c_str(), str.length());
-                #endif
-                return;
+                // 强制发送完整文本(无论是否有标点)
+                std::string segment = accumulatedText;
+                segment.erase(
+                    std::remove(segment.begin(), segment.end(), '\n'),
+                    segment.end());
+                segment.erase(
+                    std::remove(segment.begin(), segment.end(), '\r'),
+                    segment.end());
+
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "强制发送文本: %s (长度: %zu)",
+                              segment.c_str(), segment.length());
+                bool sendret = false;
+#if AI_VOICE_ENABLE
+                sendret = uapi_start_tts_single_txt((char *)segment.c_str());
+#endif
+                // 如果为true发送成功,如果发送失败等待下次发送不清空文本
+                if (sendret)
+                {
+                    // 发送后清空累积文本
+                    accumulatedText.clear();
+                    fouce_count = 0;
+                }
+                else
+                {
+                    // 发送失败,等待下次发送
+                    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "发送失败,等待下次发送,fouce_count:%d", fouce_count);
+                    fouce_count++;
+                    if (fouce_count >= 3 && !hasTtsStartSucceeded)
+                    {
+                        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "发送失败准备发送:uapi_start_tts有且只发一次");
+                        bool startOk = false;
+#if AI_VOICE_ENABLE
+                        startOk = uapi_start_tts();
+#endif
+                        fouce_count = 0;
+                        if (startOk)
+                        {
+                            hasTtsStartSucceeded = true;
+                        }
+                    }
+                }
+            }
+            else
+            {
+                // 文本过短,继续累积
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "累积文本过短(长度: %zu), 继续累积",
+                              accumulatedText.length());
+            }
+        }
+    }
+
+    // 辅助函数:按标点分段发送
+    void AiVoiceModel::sendSegment(const std::string &text, size_t pos)
+    {
+        // 提取分段(包含英文逗号)
+        std::string segment = text.substr(0, pos + 1);
+
+        // 清理文本
+        segment.erase(
+            std::remove(segment.begin(), segment.end(), '\n'),
+            segment.end());
+        segment.erase(
+            std::remove(segment.begin(), segment.end(), '\r'),
+            segment.end());
+
+        // 发送到TTS播放
+        bool ret = false;
+        if (!segment.empty())
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "按标点发送分段: %s (长度: %zu)",
+                          segment.c_str(), segment.length());
+#if AI_VOICE_ENABLE
+            ret = uapi_start_tts_single_txt((char *)segment.c_str());
+#endif
+        }
+
+        if (ret)
+        {
+            // 更新累积文本
+            if (pos + 1 < text.length())
+            {
+                accumulatedText = text.substr(pos + 1);
+            }
+            else
+            {
+                accumulatedText.clear();
+            }
+            fouce_count = 0;
+        }
+        else
+        {
+            // 发送失败,等待下次发送
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "发送失败,等待下次发送,fouce_count:%d", fouce_count);
+            fouce_count++;
+            if (fouce_count >= 3 && !hasTtsStartSucceeded)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "发送失败准备发送:uapi_start_tts有且只发一次");
+                bool startOk = false;
+#if AI_VOICE_ENABLE
+                startOk = uapi_start_tts();
+#endif
+                fouce_count = 0;
+                if (startOk)
+                {
+                    hasTtsStartSucceeded = true;
+                }
             }
         }
+    }
+
+    std::string AiVoiceModel::GetAccumulatedText(void)
+    {
+        return accumulatedText;
+    }
+
+    void AiVoiceModel::SetAiAnswerStrStr(std::string str, uint8_t type)
+    {
+        AIResponseType = type;
+        errnote = str;
         AiVoiceView *view_ = AiVoiceView::GetInstance();
-        if(view_!= nullptr )
+        if (GetSelect4gorbt() == AI_SELECT_4G) // 4G
+        {
+            if (!OHOS::AiVoiceModel::GetInstance().GetIsLimitDisplayed()) // 如果ai答案没有显示到极限了,就更新ai答案字符串
+            {
+                delete_start_line_break_str(str);
+                aiAnswerStr += str;
+                /* -------------------------------------------------------------------------- */
+                // 累积接收到的文本
+                accumulatedText += str;
+                /* -------------------------------------------------------------------------- */
+                WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "接受字的符串:%s", aiAnswerStr.c_str());
+            }
+            if (view_ != nullptr)
+            {
+                if (view_->GetAiVoiceScrollView(AIVOICE_RETURN_RESULT_TEXT_VIEWID) && view_->GetAiVoiceScrollView(AIVOICE_RETURN_RESULT_TEXT_VIEWID)->IsVisible())
+                {
+                    start_ai4g_tts_play_timer(); // 开启一个定时器,用于播放tts音频
+                    start_update_ai_answer_timer();
+                }
+            }
+        }
+        else if (GetSelect4gorbt() == AI_SELECT_BT) // 蓝牙
         {
-            if(view_->GetAiVoiceScrollView(AIVOICE_RETURN_RESULT_TEXT_VIEWID) && view_->GetAiVoiceScrollView(AIVOICE_RETURN_RESULT_TEXT_VIEWID)->IsVisible())
+            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AIResponseType = %d,errnote = %s\n", AIResponseType, errnote.c_str());
+            // 如果是:AI录音解析错误或AI 回应错误 ,或者重传多次录音数据->跳转AI回应错误界面
+            if (AIResponseType == AiVoiceModel::AI_RECORDING_PARSING_ERROR || AIResponseType == AiVoiceModel::AI_RESPONSE_ERROR || AIResponseType == AiVoiceModel::AI_BLE_ERROR)
+            {
+                SendMsgToUIService(UI_AI_JUMP_TO_RESPONDERR_VIEW, 0, (void *)errnote.c_str(), errnote.length());
+                return;
+            }
+            else if (AiVoiceModel::AI_RESPONSE_END) // 如果是AI 回应结束
+            {
+                if (errnote.empty()) // 如果没有回应数据
+                {
+                    WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::GetErrnote is empty!!");
+                    AiVoiceModel::GetInstance().SetErrnote("响应内容为空");
+                    std::string str = AiVoiceModel::GetInstance().GetErrnote();
+                    SendMsgToUIService(UI_AI_JUMP_TO_RESPONDERR_VIEW, 0, (void *)str.c_str(), str.length());
+                    return;
+                }
+            }
+            if (view_ != nullptr)
             {
-                if(!OHOS::AiVoiceModel::GetInstance().GetIsLimitDisplayed()) //如果ai答案没有显示到极限了,就更新ai答案字符串
-                { 
-                    aiAnswerStr += str;
-                    WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "接受字的符串:%s", aiAnswerStr.c_str());
-                    #ifdef SUPPORT_BLE_SERVICE
-                    SendMsgToUIService(UI_UPDATE_AI_ANSWER_STR, 0, nullptr, 0);
-                    #endif
+                if (view_->GetAiVoiceScrollView(AIVOICE_RETURN_RESULT_TEXT_VIEWID) && view_->GetAiVoiceScrollView(AIVOICE_RETURN_RESULT_TEXT_VIEWID)->IsVisible())
+                {
+                    if (!OHOS::AiVoiceModel::GetInstance().GetIsLimitDisplayed()) // 如果ai答案没有显示到极限了,就更新ai答案字符串
+                    {
+                        aiAnswerStr += str;
+                        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "接受字的符串:%s", aiAnswerStr.c_str());
+                        SendMsgToUIService(UI_UPDATE_AI_ANSWER_STR, 0, nullptr, 0);
+                    }
                 }
             }
         }
@@ -582,6 +908,8 @@ namespace OHOS
         WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "清空上次用户问题和Ai回答字符串");
         userQuestionStr = "";
         aiAnswerStr = "";
+        accumulatedText = "";
+        set_is_first_receive(true);
     }
 
     /*获取AI音频路径*/
@@ -596,7 +924,7 @@ namespace OHOS
 #endif
         int32_t AudioCaptureSample(int32_t argc, const char *argv[]);
         int32_t streamingRecordAndSend_AI(int type);
-        #define IS_SUPPORT_REALTIME_RECORD_SEND_AI 1 //是否支持实时发送录音数据
+#define IS_SUPPORT_REALTIME_RECORD_SEND_AI 1 // 是否支持实时发送录音数据
 #ifdef __cplusplus
     };
 #endif
@@ -617,9 +945,17 @@ namespace OHOS
 #if IS_SUPPORT_REALTIME_RECORD_SEND_AI
             int type = GetCurUsingAiModelType();
             WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "type = %d", type);
-            #ifdef SUPPORT_BLE_SERVICE
-            streamingRecordAndSend_AI(type);//实时发送录音数据
-            #endif
+            if (AiVoiceModel::GetInstance().GetSelect4gorbt() == AI_SELECT_BT)
+            {
+                streamingRecordAndSend_AI(type); // 实时发送录音数据
+            }
+            else if (AiVoiceModel::GetInstance().GetSelect4gorbt() == AI_SELECT_4G)
+            {
+#if AI_VOICE_ENABLE
+                LOS_Msleep(20);
+                startAudioCaptureTask();
+#endif
+            }
 #else
             std::string audioPath = AiVoiceModel::GetInstance().GetAIAudioPath();
             if (uapi_delete_files(audioPath.c_str())) // 先删除文件
@@ -637,8 +973,8 @@ namespace OHOS
 #elif CURRENT_AIAUDIO_TYPE == AIAUDIO_TYPE_MSBC
             const char *defaultArgs[6] = {"01", "msbc", "16000", "1", "16", audioPath.c_str()};
 #endif
-            uapi_save_runtime_log(RUNTIME_LOG_RECORD_START_AI);//TOOD*
-            AudioCaptureSample(6, (const char **)defaultArgs);            
+            uapi_save_runtime_log(RUNTIME_LOG_RECORD_START_AI); // TOOD*
+            AudioCaptureSample(6, (const char **)defaultArgs);
 #endif
         }
         return;
@@ -648,74 +984,43 @@ namespace OHOS
     void AiVoiceModel::StopListenAndRecordingUserQuestion(void)
     {
         WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "停止录音");
-        int32_t argc = 1;
-        uint8_t *argv = (uint8_t *)"stop";
-        AudioCaptureSample(argc, (const char **)&argv);
-        uapi_save_runtime_log(RUNTIME_LOG_RECORD_STOP_AI);//TOOD*
-        return;
-    }
-
-    /*检查录音文件是否存在并发送语音准备操作*/
-    void AiVoiceModel::CheckFileAndSendAIIsReady(void)
-    {
-        #ifdef SUPPORT_BLE_SERVICE
-        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::CheckFileAndSendAIIsReady");
-        const std::string &filePath = AIAIAudioPath;
-        FILE *file = fopen(filePath.c_str(), "r");
-        if (file != nullptr)
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "停止录音:%d", GetSelect4gorbt());
+        if (GetSelect4gorbt() == AI_SELECT_4G) // 选的是4G需要关闭asr
         {
-            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "File already exists: %s", filePath.c_str());
-
-            fseek(file, 0, SEEK_END);
-            long size = ftell(file);
-            fseek(file, 0, SEEK_SET);
-            if (size != 0)
-            {
-                auto it = selectAiModelToTextId.find(GetSelectAiModel());
-                if (it != selectAiModelToTextId.end())
-                {
-                    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "filesize = %ld,SelectAiModel = %d", size, it->second.second);
-                    if(get_ble_interval() >= BLE_CONNECT_INTERVAL_SLOW)
-                    {
-                        uapi_ble_connect_param_update(BLE_CONNECT_INTERVAL_HIGH);
-                    }
-                    send_AI_is_ready(it->second.second);
-                }
-                else
-                {
-                    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "GetSelectAiModel fail!!", size, it->second.second);
-                }
-
-                ClearQuestionAndAiAnswerStr(); // 清空上次用户问题和Ai回答字符串
-            }
-            fclose(file);
+            // uapi_stop_asr();
+            // stop_AudioCaptureProcess_AI();
+            // uapi_UI_stop_asr();
         }
-        else
+        else if (GetSelect4gorbt() == AI_SELECT_BT)
         {
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "File does not exist: %s", filePath.c_str());
-            // Handle the case where the file doesn't exist, if needed
+            int32_t argc = 1;
+            uint8_t *argv = (uint8_t *)"stop";
+            AudioCaptureSample(argc, (const char **)&argv);
         }
-        #endif
+        uapi_save_runtime_log(RUNTIME_LOG_RECORD_STOP_AI); // TOOD*
+        return;
     }
 
     void AiVoiceModel::sendAIIsReady()
     {
-        #ifdef SUPPORT_BLE_SERVICE
+#ifdef SUPPORT_BLE_SERVICE
         auto it = selectAiModelToTextId.find(GetSelectAiModel());
         if (it != selectAiModelToTextId.end())
         {
-            // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "filesize = %ld,SelectAiModel = %d", size, it->second.second);
-            if(get_ble_interval() >= BLE_CONNECT_INTERVAL_SLOW)
+
+            if (get_ble_interval() >= BLE_CONNECT_INTERVAL_SLOW)
             {
                 uapi_ble_connect_param_update(BLE_CONNECT_INTERVAL_HIGH);
             }
             send_AI_is_ready(it->second.second);
         }
-        #endif
+#endif
     }
 
     void AiVoiceModel::StatusResume(void)
     {
+        ClearQuestionAndAiAnswerStr();
+        StopListenAndRecordingUserQuestion();
         Time = THIRTY_TIME;
         AiModelConnectTimeout = 5;
         AiVoiceConnectStatus = false;
@@ -730,8 +1035,10 @@ namespace OHOS
         entryTextViewState = false;
         isClickable = false;
         isLimitDisplayed = false;
-        ClearQuestionAndAiAnswerStr();
-        StopListenAndRecordingUserQuestion();
+        AI_4G_state = false;
+        AI_BT_state = false;
+        select4gorbt = -1;
+        // init_4gai_task = false;//TOOD:之后需要销毁
     }
 
     /* -------------------------------------------------------------------------- */
@@ -745,24 +1052,30 @@ namespace OHOS
             AiVoiceModel::GetInstance().AIVoice_StopTimer();
             AiVoiceModel::GetInstance().SetErrnote("连接超时,请重新开始对话");
             std::string str = AiVoiceModel::GetInstance().GetErrnote();
-            #ifdef SUPPORT_BLE_SERVICE
+#if AI_VOICE_ENABLE
+            dinit_ai_task(); // 所有服务都删除重新连一下服务器
+#endif
             SendMsgToUIService(UI_AI_JUMP_TO_RESPONDERR_VIEW, 0, (void *)str.c_str(), str.length());
-            #endif
         }
         else
         {
-            #ifdef SUPPORT_BLE_SERVICE
-            // 4g中途断连待扩展
-            // 蓝牙的连接状态判断,如果AI思考过程中途断连,直接弹窗提示,不在硬等
-            if (get_ble_connect() == false)
+            if (AiVoiceModel::GetInstance().GetSelect4gorbt() == AI_SELECT_4G)
+            {
+                if (AiVoiceModel::GetInstance().is_need_to_jump_result_view())
+                {
+                    SendMsgToUIService(UI_AI_JUMP_TO_RESULT_VIEW, 0, nullptr, 0); // 跳转到结果界面
+                }
+                return;
+            }
+            else if (AiVoiceModel::GetInstance().GetSelect4gorbt() == AI_SELECT_BT)
             {
-                AiVoiceModel::GetInstance().SetErrnote("手机蓝牙已断开");
-                std::string str = AiVoiceModel::GetInstance().GetErrnote();
-                #ifdef SUPPORT_BLE_SERVICE
-                SendMsgToUIService(UI_AI_JUMP_TO_RESPONDERR_VIEW, 0, (void *)str.c_str(), str.length());
-                #endif
+                if (AiVoiceModel::GetInstance().GetAPPBluetoothIsConnect() == false) // 蓝牙的连接状态判断,如果AI思考过程中途断连,直接弹窗提示,不在硬等
+                {
+                    AiVoiceModel::GetInstance().SetErrnote("手机蓝牙已断开");
+                    std::string str = AiVoiceModel::GetInstance().GetErrnote();
+                    SendMsgToUIService(UI_AI_JUMP_TO_RESPONDERR_VIEW, 0, (void *)str.c_str(), str.length());
+                }
             }
-            #endif
         }
         return;
     }
@@ -852,8 +1165,10 @@ namespace OHOS
         {
             // 60s后息屏停止定时
             AiVoiceModel::GetInstance().ai_stop_screen60s_timer();
-            // 取消常亮屏
-            ScreenAlwaysOnCtr(CANCEL_SCREEN_ALWAYS_ON);
+            if (AiVoiceModel::GetInstance().GetSelect4gorbt() == AI_SELECT_BT)
+            {
+                ScreenAlwaysOnCtr(CANCEL_SCREEN_ALWAYS_ON); // 取消常亮屏
+            }
         }
     }
     static void ai_start_screen60s_timer_callback(int data)
@@ -914,7 +1229,7 @@ namespace OHOS
     void AiVoiceModel::reset_ai_screen60s_timer_time()
     {
         SCREEN_60S_TIME = 60;
-        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "reset_ai_screen60s_timer_time %d", SCREEN_60S_TIME);
+        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "reset_ai_screen60s_timer_time %d", SCREEN_60S_TIME);
         if (nullptr == g_screen60s_timer)
         {
             ScreenAlwaysOnCtr(OPEN_SCREEN_ALWAYS_ON); // 重新常亮屏
@@ -924,7 +1239,7 @@ namespace OHOS
 
     bool AiVoiceModel::get_screen60s_timer_is_stop(void)
     {
-        if(g_screen60s_timer == nullptr)
+        if (g_screen60s_timer == nullptr)
             return true;
         else
             return false;
@@ -937,12 +1252,14 @@ namespace OHOS
         LISTENING_TIMEOUT--;
         if (LISTENING_TIMEOUT <= 0)
         {
-            AiVoiceModel::GetInstance().StopListenAndRecordingUserQuestion(); // 停止聆听用户问题
-            AiVoiceModel::GetInstance().stop_listening_timer();               // 停止聆听定时器
-            if (AiVoiceView::GetInstance() && AivoiceListeningView::GetInstance())
+            AiVoiceModel::GetInstance().stop_listening_timer(); // 停止聆听定时器
+            AiVoicePresenter *p_AiVoicePresenter = AiVoicePresenter::GetInstance();
+            if (AiVoicePresenter::GetInstance() && AivoiceListeningView::GetInstance())
             {
-                AiVoiceView::GetInstance()->ChangeView(AIVOICE_LISTENING_VIEWID, AIVOICE_THINKING_VIEWID); // 切换到思考中界面
-                AiVoiceModel::GetInstance().AIVoice_StartTimer();
+#if AI_VOICE_ENABLE
+                uapi_UI_stop_asr();
+#endif
+                AiVoicePresenter::GetInstance()->ChangeViewAndLogicOperator(AIVOICE_LISTENING_VIEWID, AIVOICE_THINKING_VIEWID); // 切换到思考中界面
             }
         }
         else
@@ -1014,7 +1331,7 @@ namespace OHOS
     }
 
     static osTimerId_t g_ai_is_ready_Handle = nullptr; // 处理查询AI是否就绪定时器
-    static int8_t AI_IS_READY_TIMEOUT = 5;            // 5s钟超时
+    static int8_t AI_IS_READY_TIMEOUT = 5;             // 5s钟超时
     static void AI_IS_READY_CallbackProc(int data)
     {
         if (AI_IS_READY_TIMEOUT <= 0) // 模型连接失败有5秒超时
@@ -1027,10 +1344,32 @@ namespace OHOS
                 if ((view_->GetAiVoiceScrollView(AIVOICE_AIMODE_CONNECTING) != nullptr) &&
                     (view_->GetAiVoiceScrollView(AIVOICE_AIMODE_CONNECTING)->IsVisible()))
                 {
+#if AI_VOICE_ENABLE
+                    dinit_ai_task(); // 所有服务都删除重新连一下服务器
+#endif
                     p_AiVoicePresenter->ChangeViewAndLogicOperator(AIVOICE_AIMODE_CONNECTING, AIVOICE_AIMODEL_CONNECT_FAILED_VIEWID);
                 }
             }
         }
+        else
+        {
+            if (AiVoiceModel::GetInstance().GetSelect4gorbt() == AI_SELECT_4G)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "GetSelect4gorbt() == AI_SELECT_4G");
+                if (AiVoiceModel::GetInstance().GetInit_4gai_task())
+                {
+                    uint8_t state = 0;
+#if AI_VOICE_ENABLE
+                    state = get_asr_is_ready_start();
+#endif
+                    if (state)
+                    {
+                        bool state = true;
+                        SendMsgToUIService(UI_AI_JUMP_TO_LISTENING_VIEW, 0, &state, sizeof(bool));
+                    }
+                }
+            }
+        }
         return;
     }
     static void AI_IS_READY_Callback(int data)
@@ -1094,34 +1433,495 @@ namespace OHOS
         }
     }
 
-    // 设置选择的ai模型
-    void AiVoiceModel::SetSelectAiModel(int index)
-    {
-        ConfigModel::GetInstance()->SetSelectAiModel(index);
-    }
-
-    int AiVoiceModel::GetSelectAiModel(void)
-    {
-        return ConfigModel::GetInstance()->GetSelectAiModel();
-    }
-
-    /*获取已选择的ai模型的textid*/
-    int AiVoiceModel::GetAiModelTextId()
+    /* -------------------------------------------------------------------------- */
+    static osTimerId_t g_ai4g_is_suc_connected_Handle = nullptr; // 处理AI4G连接定时器
+    static uint8_t AI4G_IS_SUC_CON_TIME = 25;
+    static int8_t AI4G_IS_SUC_CON_TIMEOUT = AI4G_IS_SUC_CON_TIME; // AI4G_IS_SUC_CON_TIME秒超时
+    static void AI4G_IS_SUC_CON_CallbackProc(int data)
     {
-        #if 0
-        int language = ConfigModel::GetInstance()->GetLanguage();
-        int textId;
-
-        if (language == 0)
+        AiVoiceView *view_ = AiVoiceView::GetInstance();
+        AiVoicePresenter *p_AiVoicePresenter = AiVoicePresenter::GetInstance();
+        if (AI4G_IS_SUC_CON_TIMEOUT <= 0) // 4g服务器连接失败
         {
-            selectAiModelToTextId = {
-                {0, {STR_AIMODES_WENXINYIYAN, 0}},
+            AiVoiceModel::GetInstance().stop_ai4g_connect_timer();
+            if (view_ != nullptr && p_AiVoicePresenter != nullptr)
+            {
+                if ((view_->GetAiVoiceScrollView(AIVOICE_4GSERVICECON_VIEW) != nullptr) &&
+                    (view_->GetAiVoiceScrollView(AIVOICE_4GSERVICECON_VIEW)->IsVisible()))
+                {
+#if AI_VOICE_ENABLE
+                    dinit_ai_task(); // 所有服务都删除重新连一下服务器
+#endif
+                    p_AiVoicePresenter->ChangeViewAndLogicOperator(AIVOICE_4GSERVICECON_VIEW, AIVOICE_AIMODEL_CONNECT_FAILED_VIEWID);
+                }
+            }
+        }
+        else
+        {
+            if (view_ != nullptr && p_AiVoicePresenter != nullptr)
+            {
+#if AI_VOICE_ENABLE
+                if (uapi_get_server_state_is_end())
+                {
+                    init_ai_task(AiVoiceModel::GetInstance().GetCurUsing4GAiModelType());
+                    return;
+                }
+
+                if (AiVoiceModel::GetInstance().GetInit_4gai_task())
+                {
+                    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "4gAi服务初始化成功");
+                    AiVoiceModel::GetInstance().stop_ai4g_connect_timer();
+                    p_AiVoicePresenter->ChangeViewAndLogicOperator(AIVOICE_4GSERVICECON_VIEW, AIVOICE_AIMODE_CONNECTING);
+                }
+#endif
+            }
+        }
+        return;
+    }
+    static void AI4G_IS_SUC_CON_Callback(int data)
+    {
+        AI4G_IS_SUC_CON_TIMEOUT--;
+        GraphicService::GetInstance()->PostGraphicEvent(std::bind(AI4G_IS_SUC_CON_CallbackProc, data));
+    }
+    /*处理AI4G连接定时器到期时的处理*/
+    void AiVoiceModel::start_ai4g_connect_timer(uint32_t interval)
+    {
+        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::start_ai4g_connect_timer");
+        /* -------------------------- 1.检查定时器是否已经存在,如果存在则返回 ------------------------- */
+        if (g_ai4g_is_suc_connected_Handle != nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Timer already exists!!");
+            return;
+        }
+        /* --------------------------------- 2.创建定时器 -------------------------------- */
+        g_ai4g_is_suc_connected_Handle = osTimerNew((osTimerFunc_t)AI4G_IS_SUC_CON_Callback, osTimerPeriodic, nullptr, nullptr);
+        // 检查定时器创建是否成功
+        if (g_ai4g_is_suc_connected_Handle == nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Timer create failed!!");
+            return;
+        }
+        /* ----------------------------- 3.将毫秒转换为系统时钟节拍数 ---------------------------- */
+        int tick = osMs2Tick(interval);
+        /* --------------------------------- 4.启动定时器 -------------------------------- */
+        osStatus_t ret = osTimerStart(g_ai4g_is_suc_connected_Handle, tick);
+        /* -------------------- 5.检查定时器启动是否成功,如果启动失败,删除定时器并置为 nullptr -------------------- */
+        if (ret != osOK)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "osTimerDelete failed, ret = %lx!!", ret);
+            if (g_ai4g_is_suc_connected_Handle != nullptr)
+            {
+                ret = osTimerDelete(g_ai4g_is_suc_connected_Handle);
+            }
+            g_ai4g_is_suc_connected_Handle = nullptr;
+            return;
+        }
+        return;
+    }
+
+    void AiVoiceModel::stop_ai4g_connect_timer(void)
+    {
+        // 检查定时器是否存在
+        if (g_ai4g_is_suc_connected_Handle != nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::stop_ai4g_connect_timer");
+            osTimerStop(g_ai4g_is_suc_connected_Handle);
+            // 删除定时器并置为 nullptr
+            osStatus_t ret = osTimerDelete(g_ai4g_is_suc_connected_Handle);
+            if (ret != osOK)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "osTimerDelete failed, ret = %lx!!", ret);
+            }
+            g_ai4g_is_suc_connected_Handle = nullptr;
+            AI4G_IS_SUC_CON_TIMEOUT = AI4G_IS_SUC_CON_TIME;
+        }
+    }
+
+    /* -------------------------------- tts播放定时器 -------------------------------- */
+    static osTimerId_t g_ai4g_is_start_tts_play_Handle = nullptr;
+    static constexpr const int8_t NUMBER_TEN = 15;
+    static int8_t AI4G_IS_START_TTS_PLAY_CNT = NUMBER_TEN;
+    static uint8_t tts_record_flag = 0;
+    // 添加一个静态变量用于跟踪连续出现0的次数
+    static int s_tts_tick_zero_count = 0;
+    static void AI4G_IS_START_TTS_CallbackProc(int data)
+    {
+        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AI4G_IS_START_TTS_CallbackProc:%s", AiVoiceModel::GetInstance().GetAccumulatedText().c_str());
+        AiVoiceModel::GetInstance().GetInit_4gai_task(); // 获取4gai服务状态
+        uint8_t tts_state = 0;
+#if AI_VOICE_ENABLE
+        tts_state = get_ai_tts_server_init_flag();
+#endif
+        if (tts_state == 0) // tts服务如果断开了,就停止定时器
+        {
+            s_tts_tick_zero_count++; // 增加连续0的次数
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "s_tts_tick_zero_count count: %d", s_tts_tick_zero_count);
+            if (s_tts_tick_zero_count >= 10) // 如果连续出现10次0,就停止定时器
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "tts_server disconnect...");
+                AiVoiceModel::GetInstance().stop_ai4g_tts_play_timer();
+                return;
+            }
+        }
+
+        // 无文本时停止定时器
+        if (AiVoiceModel::GetInstance().GetAccumulatedText().empty())
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "没有文本了准备发送:stop_ai4g_tts_play_timer");
+            AiVoiceModel::GetInstance().stop_ai4g_tts_play_timer();
+            return;
+        }
+
+#if AI_VOICE_ENABLE
+        if (!get_ai_osal_msg_queue_is_full())
+        {
+            AiVoiceModel::GetInstance().ProcessTextByPunctuation();
+        }
+#endif
+        return;
+    }
+
+    static void AI4G_IS_START_TTS_Callback(int data)
+    {
+        AI4G_IS_START_TTS_CallbackProc(data);
+        // GraphicService::GetInstance()->PostGraphicEvent(std::bind(AI4G_IS_START_TTS_CallbackProc, data));
+    }
+
+    void AiVoiceModel::start_ai4g_tts_play_timer(uint32_t interval)
+    {
+        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::start_ai4g_tts_play_timer");
+        // AI4G_IS_START_TTS_PLAY_CNT = NUMBER_TEN;
+        /* -------------------------- 1.检查定时器是否已经存在,如果存在则返回 ------------------------- */
+        if (g_ai4g_is_start_tts_play_Handle != nullptr)
+        {
+            // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Timer already exists!!");
+            return;
+        }
+        /* --------------------------------- 2.创建定时器 -------------------------------- */
+        g_ai4g_is_start_tts_play_Handle = osTimerNew((osTimerFunc_t)AI4G_IS_START_TTS_Callback, osTimerPeriodic, nullptr, nullptr);
+        // 检查定时器创建是否成功
+        if (g_ai4g_is_start_tts_play_Handle == nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Timer create failed!!");
+            return;
+        }
+        /* ----------------------------- 3.将毫秒转换为系统时钟节拍数 ---------------------------- */
+        int tick = osMs2Tick(interval);
+        /* --------------------------------- 4.启动定时器 -------------------------------- */
+        osStatus_t ret = osTimerStart(g_ai4g_is_start_tts_play_Handle, tick);
+        /* -------------------- 5.检查定时器启动是否成功,如果启动失败,删除定时器并置为 nullptr -------------------- */
+        if (ret != osOK)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "osTimerDelete failed, ret = %lx!!", ret);
+            if (g_ai4g_is_start_tts_play_Handle != nullptr)
+            {
+                ret = osTimerDelete(g_ai4g_is_start_tts_play_Handle);
+            }
+            g_ai4g_is_start_tts_play_Handle = nullptr;
+            return;
+        }
+        return;
+    }
+
+    void AiVoiceModel::stop_ai4g_tts_play_timer(void)
+    {
+        // 检查定时器是否存在
+        if (g_ai4g_is_start_tts_play_Handle != nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "stop_ai4g_tts_play_timer");
+            osTimerStop(g_ai4g_is_start_tts_play_Handle);
+            // 删除定时器并置为 nullptr
+            osStatus_t ret = osTimerDelete(g_ai4g_is_start_tts_play_Handle);
+            if (ret != osOK)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "osTimerDelete failed, ret = %lx!!", ret);
+            }
+            g_ai4g_is_start_tts_play_Handle = nullptr;
+            AI4G_IS_START_TTS_PLAY_CNT = NUMBER_TEN;
+            s_tts_tick_zero_count = 0; // 重置计数器
+            fouce_count = 0;
+
+            start_uapi_stop_tts_timer();
+        }
+    }
+
+    static osTimerId_t g_start_ai_answer_update_Handle = nullptr;
+    static constexpr const int8_t NUMBER_THREE = 3;
+    static int8_t START_UPDATE_AIANSWER_CNT = NUMBER_THREE;
+    static void AI4G_START_AI_ANSWER_CallbackProc(int data)
+    {
+        START_UPDATE_AIANSWER_CNT--;
+        if (START_UPDATE_AIANSWER_CNT <= 0)
+        {
+            AiVoiceModel::GetInstance().stop_update_ai_answer_timer();
+        }
+        else
+        {
+            SendMsgToUIService(UI_UPDATE_AI_ANSWER_STR, 0, nullptr, 0);
+        }
+    }
+
+    static void AI4G_START_AI_ANSWER_Callback(int data)
+    {
+        AI4G_START_AI_ANSWER_CallbackProc(data);
+        // GraphicService::GetInstance()->PostGraphicEvent(std::bind(AI4G_START_AI_ANSWER_CallbackProc, data));
+    }
+
+    void AiVoiceModel::start_update_ai_answer_timer(uint32_t interval)
+    {
+        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::start_update_ai_answer_timer");
+        START_UPDATE_AIANSWER_CNT = NUMBER_THREE;
+        /* -------------------------- 1.检查定时器是否已经存在,如果存在则返回 ------------------------- */
+        if (g_start_ai_answer_update_Handle != nullptr)
+        {
+            // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Timer already exists!!");
+            return;
+        }
+        /* --------------------------------- 2.创建定时器 -------------------------------- */
+        g_start_ai_answer_update_Handle = osTimerNew((osTimerFunc_t)AI4G_START_AI_ANSWER_Callback, osTimerPeriodic, nullptr, nullptr);
+        // 检查定时器创建是否成功
+        if (g_start_ai_answer_update_Handle == nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Timer create failed!!");
+            return;
+        }
+        /* ----------------------------- 3.将毫秒转换为系统时钟节拍数 ---------------------------- */
+        int tick = osMs2Tick(interval);
+        /* --------------------------------- 4.启动定时器 -------------------------------- */
+        osStatus_t ret = osTimerStart(g_start_ai_answer_update_Handle, tick);
+        /* -------------------- 5.检查定时器启动是否成功,如果启动失败,删除定时器并置为 nullptr -------------------- */
+        if (ret != osOK)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "osTimerDelete failed, ret = %lx!!", ret);
+            if (g_start_ai_answer_update_Handle != nullptr)
+            {
+                ret = osTimerDelete(g_start_ai_answer_update_Handle);
+            }
+            g_start_ai_answer_update_Handle = nullptr;
+            return;
+        }
+        return;
+    }
+
+    void AiVoiceModel::stop_update_ai_answer_timer(void)
+    {
+        if (g_start_ai_answer_update_Handle != nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "stop_update_ai_answer_timer");
+            osTimerStop(g_start_ai_answer_update_Handle);
+            // 删除定时器并置为 nullptr
+            osStatus_t ret = osTimerDelete(g_start_ai_answer_update_Handle);
+            if (ret != osOK)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "osTimerDelete failed, ret = %lx!!", ret);
+            }
+            g_start_ai_answer_update_Handle = nullptr;
+            START_UPDATE_AIANSWER_CNT = NUMBER_THREE;
+        }
+    }
+
+    static osTimerId_t g_uapi_stop_tts_Handle = nullptr;
+    static void AI4G_UAPI_STOP_TTS_CallbackProc(int data)
+    {
+        AiVoiceModel::GetInstance().stop_uapi_stop_tts_timer();
+    }
+
+    static void AI4G_UAPI_STOP_TTS_Callback(int data)
+    {
+        AI4G_UAPI_STOP_TTS_CallbackProc(data);
+        // GraphicService::GetInstance()->PostGraphicEvent(std::bind(AI4G_UAPI_STOP_TTS_CallbackProc, data));
+    }
+
+    void AiVoiceModel::start_uapi_stop_tts_timer(uint32_t interval)
+    {
+        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceModel::start_uapi_stop_tts_timer");
+        /* -------------------------- 1.检查定时器是否已经存在,如果存在则返回 ------------------------- */
+        if (g_uapi_stop_tts_Handle != nullptr)
+        {
+            // WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Timer already exists!!");
+            return;
+        }
+        /* --------------------------------- 2.创建定时器 -------------------------------- */
+        g_uapi_stop_tts_Handle = osTimerNew((osTimerFunc_t)AI4G_UAPI_STOP_TTS_Callback, osTimerPeriodic, nullptr, nullptr);
+        // 检查定时器创建是否成功
+        if (g_uapi_stop_tts_Handle == nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Timer create failed!!");
+            return;
+        }
+        /* ----------------------------- 3.将毫秒转换为系统时钟节拍数 ---------------------------- */
+        int tick = osMs2Tick(interval);
+        /* --------------------------------- 4.启动定时器 -------------------------------- */
+        osStatus_t ret = osTimerStart(g_uapi_stop_tts_Handle, tick);
+        /* -------------------- 5.检查定时器启动是否成功,如果启动失败,删除定时器并置为 nullptr -------------------- */
+        if (ret != osOK)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "osTimerDelete failed, ret = %lx!!", ret);
+            if (g_uapi_stop_tts_Handle != nullptr)
+            {
+                ret = osTimerDelete(g_uapi_stop_tts_Handle);
+            }
+            g_uapi_stop_tts_Handle = nullptr;
+            return;
+        }
+    }
+
+    void AiVoiceModel::stop_uapi_stop_tts_timer(void)
+    {
+        // 检查定时器是否存在
+        if (g_uapi_stop_tts_Handle != nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "stop_uapi_stop_tts_timer");
+            osTimerStop(g_uapi_stop_tts_Handle);
+            // 删除定时器并置为 nullptr
+            osStatus_t ret = osTimerDelete(g_uapi_stop_tts_Handle);
+            if (ret != osOK)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "osTimerDelete failed, ret = %lx!!", ret);
+            }
+            g_uapi_stop_tts_Handle = nullptr;
+            if (g_ai4g_is_start_tts_play_Handle == nullptr)
+            {
+                hasTtsStartSucceeded = false;
+#if AI_VOICE_ENABLE
+                uapi_stop_tts();
+#endif
+            }
+        }
+    }
+
+    // 设置选择的ai模型
+    void AiVoiceModel::SetSelectAiModel(int index)
+    {
+#if defined(AI_VOICE_N9)
+        ConfigModel::GetInstance()->SetSelectAiModel(0);
+#else
+        ConfigModel::GetInstance()->SetSelectAiModel(index);
+#endif
+    }
+
+    int AiVoiceModel::GetSelectAiModel(void)
+    {
+        return ConfigModel::GetInstance()->GetSelectAiModel();
+    }
+
+    void AiVoiceModel::SetAI_4G_state(bool state)
+    {
+        AI_4G_state = state;
+    }
+    bool AiVoiceModel::GetAI_4G_state(void)
+    {
+        return AI_4G_state;
+    }
+    void AiVoiceModel::SetAI_BT_state(bool state)
+    {
+        AI_BT_state = state;
+    }
+    bool AiVoiceModel::GetAI_BT_state(void)
+    {
+        return AI_BT_state;
+    }
+    void AiVoiceModel::SetInit_4gai_task(bool state)
+    {
+        init_4gai_task = state;
+    }
+    bool AiVoiceModel::GetInit_4gai_task(void)
+    {
+        uint8_t asr_state = 0;
+        uint8_t chat_state = 0;
+        uint8_t tts_state = 0;
+#if AI_VOICE_ENABLE
+        asr_state = get_ai_asr_service_init_flag();
+        chat_state = get_ai_chat_service_init_flag();
+        tts_state = get_ai_tts_server_init_flag();
+#endif
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "asr_state:%d,chat_state:%d,tts_state:%d", asr_state, chat_state, tts_state);
+        if ((asr_state == 1) && (chat_state == 1) && (tts_state == 1))
+        {
+            init_4gai_task = true;
+        }
+        else
+        {
+            init_4gai_task = false;
+        }
+        return init_4gai_task;
+    }
+
+    void AiVoiceModel::SetSelect4gorbt(int state)
+    {
+        select4gorbt = state;
+    }
+    int AiVoiceModel::GetSelect4gorbt(void)
+    {
+        return select4gorbt;
+    }
+    // 打断tts播放
+    void AiVoiceModel::cancel_tts_play(void)
+    {
+#if AI_VOICE_ENABLE
+        tts_server_deinit();
+#endif
+    }
+
+    // 是否需要跳转到结果视图
+    bool AiVoiceModel::is_need_to_jump_result_view(void)
+    {
+        if (userQuestionStr.empty())
+        {
+            return false;
+        }
+        return true;
+    }
+
+    bool AiVoiceModel::getentryTextViewState(void)
+    {
+        return entryTextViewState;
+    }
+
+    bool AiVoiceModel::get_is_first_receive()
+    {
+        return isFirstReceive;
+    }
+
+    void AiVoiceModel::set_is_first_receive(bool val)
+    {
+        isFirstReceive = val;
+    }
+
+    // 删除开始的换行符
+    void AiVoiceModel::delete_start_line_break_str(std::string &str)
+    {
+        if (GetSelect4gorbt() == AI_SELECT_4G && GetAiModelTextId() == STR_AIMODELS_DOUBAO)
+        {
+            if (isFirstReceive)
+            {
+                isFirstReceive = false;
+                // 检查是否以"\n\n"开头
+                if (str.size() >= 2 && str[0] == '\n' && str[1] == '\n')
+                {
+                    // 去除开头的两个换行符
+                    str = str.substr(2);
+                }
+            }
+        }
+    }
+
+    /*获取已选择的ai模型的textid*/
+    int AiVoiceModel::GetAiModelTextId()
+    {
+#if 0
+        int language = ConfigModel::GetInstance()->GetLanguage();
+        int textId;
+
+        if (language == 0)
+        {
+            selectAiModelToTextId = {
+                {0, {STR_AIMODES_WENXINYIYAN, 0}},
                 {1, {STR_AIMODES_KIMI, 2}},
                 {2, {STR_AIMODELS_DOUBAO, 3}},
                 // {3, {STR_TONGYI_QIANWEN, 4}},
                 {3, {STR_DEEPSEEK, 4}},
-                // {4, {STR_IFLYTEK_SPARK, 5}},
-                {4, {STR_AIMODES_LINGXI, 5}},
+                {4, {STR_IFLYTEK_SPARK, 5}},
                 {5, {STR_AIMODES_CHATGPT, 1}},
             };
             textId = STR_AIMODES_WENXINYIYAN;
@@ -1135,22 +1935,38 @@ namespace OHOS
                 {3, {STR_AIMODELS_DOUBAO, 3}},
                 // {4, {STR_TONGYI_QIANWEN, 4}},
                 {4, {STR_DEEPSEEK, 4}},
-                // {5, {STR_IFLYTEK_SPARK, 5}},
-                {5, {STR_AIMODES_LINGXI, 5}},
+                {5, {STR_IFLYTEK_SPARK, 5}},
             };
             textId = STR_AIMODES_CHATGPT;
         }
-        #endif
-        //客户新需求需要改模型顺序:
+#endif
+#ifdef AI_VOICE_JIUTIAN
+        int textId = 0;
+        selectAiModelToTextId = {
+            {0, {STR_DEEPSEEK, 4}},
+            {1, {STR_JIUTIAN, 5}},
+            {2, {STR_AIMODELS_DOUBAO, 3}},
+            {3, {STR_AIMODES_WENXINYIYAN, 0}},
+            {4, {STR_AIMODES_KIMI, 2}},
+            {5, {STR_AIMODES_CHATGPT, 1}},
+        };
+        textId = STR_DEEPSEEK;
+#elif defined(AI_VOICE_N9)
+        int textId = 0;
+        selectAiModelToTextId = {
+            {0, {STR_AIMODELS_DOUBAO, 3}},
+        };
+        textId = STR_AIMODELS_DOUBAO;
+#else
+        // 客户新需求需要改模型顺序:
         int textId = 0;
         selectAiModelToTextId = {
             {0, {STR_DEEPSEEK, 4}},
-            {1, {STR_AIMODES_CHATGPT, 1}},
+            {1, {STR_JIUTIAN, 5}},
             {2, {STR_AIMODELS_DOUBAO, 3}},
             {3, {STR_AIMODES_WENXINYIYAN, 0}},
             {4, {STR_AIMODES_KIMI, 2}},
-            // {5, {STR_IFLYTEK_SPARK, 5}},
-            {5, {STR_AIMODES_LINGXI, 5}},
+            {5, {STR_AIMODES_CHATGPT, 1}},
         };
         textId = STR_DEEPSEEK;
 
@@ -1160,8 +1976,41 @@ namespace OHOS
         {
             return it->second.first;
         }
-
+#endif
         return textId;
     }
 
 }
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C"
+{
+#endif                              /* __cplusplus */
+#endif                              /* __cplusplus */
+    uint8_t getselect4gorbtai(void) // 获取AI模型选择的是4G还是蓝牙
+    {
+        if (OHOS::AiVoiceModel::GetInstance().GetSelect4gorbt() == AI_SELECT_4G)
+        {
+            return 1;
+        }
+        return 0;
+    }
+
+    static uint8_t clear_queue_stream = 0;
+    uint8_t get_clear_queue_stream(void)
+    {
+        return clear_queue_stream;
+    }
+
+    // 清空队列中可能存在的音频数据
+    void set_clear_queue_stream(uint8_t state)
+    {
+        clear_queue_stream = state;
+    }
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* __cplusplus */
\ No newline at end of file
index 3b04183..ab99d3c 100644 (file)
 
 #include <unistd.h>
 #include "gfx_utils/mem_check.h"
-
 #include "player/include/PlayersModel.h"
-
 #include "NativeRegisterManager.h"
+#include "aivoice/include/AiVoiceSelectView.h"
+#include "graphic_service.h"
+#include "cat1_ws.h"
 namespace OHOS
 {
 
     REGIST_MENU_PRO(VIEW_AI_VOICE, AiVoiceView, AiVoicePresenter,
-        PNG_APPLIST_AIVOICE_IMAGE_BIG, PNG_APPLIST_AIVOICE_IMAGE,PNG_APPLIST_AIVOICE_IMAGE, "AI全家桶", STR_AI_FAMILY_MEALS);
+                    PNG_APPLIST_AIVOICE_IMAGE_BIG, PNG_APPLIST_AIVOICE_IMAGE, PNG_APPLIST_AIVOICE_IMAGE, "AI全家桶", STR_AI_FAMILY_MEALS);
+
+#ifdef __cplusplus
+    extern "C"
+    {
+#endif
+#include "pm.h"
+#include "pm_veto.h"
+#include <asm/delay.h>
+#include <aivoice/include/AiVoiceModelC.h>
+#include <los_base.h>
+        extern void set_need_tts_reconnect(uint8_t flag);
+
+        void remove_4GAI_vote(void)
+        {
+            uint8_t cnt = pm_veto_get_id_cnt(PM_ID_4G_AI);
+            if (cnt == 1)
+            {
+                uapi_pm_remove_sleep_veto(PM_ID_4G_AI);
+            }
+        }
+
+        void add_4GAI_vote(void)
+        {
+            uint8_t cnt = pm_veto_get_id_cnt(PM_ID_4G_AI);
+            if (cnt == 0)
+            {
+                uapi_pm_add_sleep_veto(PM_ID_4G_AI);
+            }
+        }
 
+#ifdef __cplusplus
+    }
+#endif
 #define BLE_CONNECT_INTERVAL_HIGH_AI 10
     // 当前Presenter属性实例化的内存指针
     static AiVoicePresenter *g_pAiVoicePresenter = nullptr;
@@ -70,33 +103,16 @@ namespace OHOS
         ScreenAlwaysOnCtr(OPEN_SCREEN_ALWAYS_ON);
         // 开启一个60s取消长亮屏timer
         model->ai_start_screen60s_timer();
-#ifdef SUPPORT_BLE_SERVICE
-        uapi_ble_connect_param_update(BLE_CONNECT_INTERVAL_HIGH_AI);
-#endif
-    }
-
-    // 页面已经展示后的调用逻辑
-    void AiVoicePresenter::OnResume(void)
-    {
-        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnResume");
-        Presenter<AiVoiceView>::OnResume();
-        if (view_ == nullptr)
-        {
-            return;
-        }
-    }
+        add_4GAI_vote(); // 4g投票
 
-    // 页面准备切换到后台前执行的逻辑
-    void AiVoicePresenter::OnPause(void)
-    {
-        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnPause");
-        Presenter<AiVoiceView>::OnPause();
+        uapi_ble_connect_param_update(BLE_CONNECT_INTERVAL_HIGH_AI);
+        Audio::AudioManager::GetInstance().SetVolume(AUDIO_STREAM_VOICE_ASSISTANT, 100);
     }
 
     // 页面完全置于后台时的逻辑。
     void AiVoicePresenter::OnStop(void)
     {
-        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnStop");
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnStop start");
         Presenter<AiVoiceView>::OnStop();
         ScreenAlwaysOnCtr(CANCEL_SCREEN_ALWAYS_ON);
         model->StatusResume();
@@ -104,25 +120,54 @@ namespace OHOS
         model->ai_stop_screen60s_timer();
         model->stop_listening_timer();
         model->stop_ai_isready_timer();
-        #ifdef SUPPORT_BLE_SERVICE
+        model->stop_ai4g_connect_timer();
+        model->stop_ai4g_tts_play_timer();
+        model->stop_update_ai_answer_timer();
+        model->stop_uapi_stop_tts_timer();
+        remove_4GAI_vote(); // 移除4g投票
+#if AI_VOICE_ENABLE
+        dinit_ai_task();
+        ai_cleanup_resources();
+#endif
+
         uapi_ble_connect_param_update(BLE_CONNECT_INTERVAL_SLOW);
-        #endif
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnStop end");
+        return;
     }
 
     /*调转到返回结果界面*/
     bool AiVoicePresenter::JumpToReturnResultTextView(void)
     {
         WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::JumpToReturnResultTextView");
-        if (view_->GetAiVoiceScrollView(AIVOICE_THINKING_VIEWID) != nullptr &&
-            view_->GetAiVoiceScrollView(AIVOICE_THINKING_VIEWID)->IsVisible())
+        if (model->GetSelect4gorbt() == AI_SELECT_4G)
         {
             preHeight = 0;
-            ChangeViewAndLogicOperator(AIVOICE_THINKING_VIEWID, AIVOICE_RETURN_RESULT_TEXT_VIEWID);
+            if (model->GetCurView() == AIVOICE_LISTENING_VIEWID || model->GetCurView() == AIVOICE_THINKING_VIEWID)
+            {
+                if (view_->GetAiVoiceScrollView(AIVOICE_LISTENING_VIEWID) || view_->GetAiVoiceScrollView(AIVOICE_THINKING_VIEWID))
+                {
+                    ChangeViewAndLogicOperator(model->GetCurView(), AIVOICE_RETURN_RESULT_TEXT_VIEWID);
+                }
+                else
+                {
+                    WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::JumpToReturnResultTextView fail");
+                    return false;
+                }
+            }
         }
-        else
+        else if (model->GetSelect4gorbt() == AI_SELECT_BT)
         {
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::JumpToReturnResultTextView fail");
-            return false;
+            if (view_->GetAiVoiceScrollView(AIVOICE_THINKING_VIEWID) != nullptr &&
+                view_->GetAiVoiceScrollView(AIVOICE_THINKING_VIEWID)->IsVisible())
+            {
+                preHeight = 0;
+                ChangeViewAndLogicOperator(AIVOICE_THINKING_VIEWID, AIVOICE_RETURN_RESULT_TEXT_VIEWID);
+            }
+            else
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::JumpToReturnResultTextView fail");
+                return false;
+            }
         }
         return true;
     }
@@ -131,22 +176,42 @@ namespace OHOS
     bool AiVoicePresenter::ChangeToAIVoiceListeningView(bool val)
     {
         WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::ChangeToAIVoiceListeningView");
-        if (view_->GetAiVoiceScrollView(AIVOICE_AIMODE_CONNECTING) != nullptr && view_->GetAiVoiceScrollView(AIVOICE_AIMODE_CONNECTING)->IsVisible())
+        if (model->GetSelect4gorbt() == AI_SELECT_4G)
         {
-            model->stop_ai_isready_timer(); // 停止定时器
-            if (val)                        /*如果查询的AI模型可用跳转到聆听中界面*/
+            if (val) /*如果查询的AI模型可用跳转到聆听中界面*/
             {
-                ChangeViewAndLogicOperator(AIVOICE_AIMODE_CONNECTING, AIVOICE_LISTENING_VIEWID);
+                ChangeViewAndLogicOperator(model->GetCurView(), AIVOICE_LISTENING_VIEWID);
             }
             else
             {
-                if(model->GetAiModelTextId() == STR_AIMODES_CHATGPT) //如果当前是在chatgpt模型*/
+                if (model->GetAiModelTextId() == STR_AIMODES_CHATGPT) // 如果当前是在chatgpt模型*/
                 {
-                    ChangeViewAndLogicOperator(AIVOICE_AIMODE_CONNECTING, AIVOICE_NOTSETAPIKEYS); /*开始对话界面->API Keys notset界面*/
+                    ChangeViewAndLogicOperator(model->GetCurView(), AIVOICE_NOTSETAPIKEYS); /*开始对话界面->API Keys notset界面*/
                 }
                 else
                 {
-                    ChangeViewAndLogicOperator(AIVOICE_AIMODE_CONNECTING, AIVOICE_AIMODEL_CONNECT_FAILED_VIEWID);
+                    ChangeViewAndLogicOperator(model->GetCurView(), AIVOICE_AIMODEL_CONNECT_FAILED_VIEWID);
+                }
+            }
+        }
+        else if (model->GetSelect4gorbt() == AI_SELECT_BT)
+        {
+            if (view_->GetAiVoiceScrollView(AIVOICE_AIMODE_CONNECTING) != nullptr && view_->GetAiVoiceScrollView(AIVOICE_AIMODE_CONNECTING)->IsVisible())
+            {
+                if (val) /*如果查询的AI模型可用跳转到聆听中界面*/
+                {
+                    ChangeViewAndLogicOperator(model->GetCurView(), AIVOICE_LISTENING_VIEWID);
+                }
+                else
+                {
+                    if (model->GetAiModelTextId() == STR_AIMODES_CHATGPT) // 如果当前是在chatgpt模型*/
+                    {
+                        ChangeViewAndLogicOperator(model->GetCurView(), AIVOICE_NOTSETAPIKEYS); /*开始对话界面->API Keys notset界面*/
+                    }
+                    else
+                    {
+                        ChangeViewAndLogicOperator(model->GetCurView(), AIVOICE_AIMODEL_CONNECT_FAILED_VIEWID);
+                    }
                 }
             }
         }
@@ -175,7 +240,7 @@ namespace OHOS
 
     void AiVoicePresenter::FunctionKeyOnClickToChangeAIModel(void)
     {
-        if(view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID) && view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID)->IsVisible() == true)
+        if (view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID) && view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID)->IsVisible() == true)
         {
             int index = model->GetSelectAiModel() + 1;
             if (index >= AIMODES_MAX_NUM)
@@ -193,12 +258,12 @@ namespace OHOS
     // 右滑切换模型
     void AiVoicePresenter::DragLeftToRightChangeAIModel(void)
     {
-        if(view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID) && view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID)->IsVisible() == true)
+        if (view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID) && view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID)->IsVisible() == true)
         {
-            int index = model->GetSelectAiModel() + 1;
-            if (index >= AIMODES_MAX_NUM)
+            int index = model->GetSelectAiModel() - 1;
+            if (index < 0)
             {
-                index = 0;
+                index = AIMODES_CHATGPT;
             }
             WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiModelsPresenter::index = %d", index);
             model->SetSelectAiModel(index);
@@ -210,12 +275,12 @@ namespace OHOS
     // 左滑切换模型
     void AiVoicePresenter::DragRightToLetfChangeAIModel(void)
     {
-        if(view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID) && view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID)->IsVisible() == true)
+        if (view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID) && view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID)->IsVisible() == true)
         {
-            int index = model->GetSelectAiModel() - 1;
-            if (index < 0)
+            int index = model->GetSelectAiModel() + 1;
+            if (index >= AIMODES_MAX_NUM)
             {
-                index = AIMODES_CHATGPT;
+                index = 0;
             }
             WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiModelsPresenter::index = %d", index);
             model->SetSelectAiModel(index);
@@ -226,8 +291,17 @@ namespace OHOS
 
     bool AiVoicePresenter::ChangeViewAndLogicOperator(int16_t hideView, int16_t showView)
     {
-        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::ChangeViewOperator");
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::ChangeViewOperator");
+
+        // 加锁,作用域结束时自动释放锁
+        // std::lock_guard<std::mutex> lock(m_mutex);
 
+        bool isSameView = (hideView == showView);
+        if (isSameView)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Same view no need to change");
+            return false;
+        }
         if (hideView > MAX_AIVOICE_VIEWID)
         {
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Overstep ones bounds");
@@ -242,31 +316,15 @@ namespace OHOS
         switch (hideView)
         {
         case AIVOICE_STARTCHAT_VIEWID:
-            model->QuerySelectedAiModelIsConnect(); /*查询用户选择的AI模型是否已经连接*/
-            if (showView == AIVOICE_LISTENING_VIEWID)
-            {
-                model->StartListenAndRecordingUserQuestion();
-            }
-            else if (showView == AIVOICE_AIMODE_CONNECTING)
-            {
-                model->start_ai_isready_timer(); /*开启一个查询AI模型是否连接成功定时器*/
-            }
             break;
 
         case AIVOICE_AIMODE_CONNECTING:
-            if (showView == AIVOICE_LISTENING_VIEWID)
-            {
-                model->StartListenAndRecordingUserQuestion();
-            }
+            model->stop_ai_isready_timer(); // 停止定时器
             break;
 
         case AIVOICE_LISTENING_VIEWID:
             model->StopListenAndRecordingUserQuestion();
             model->stop_listening_timer();
-            if (showView == AIVOICE_THINKING_VIEWID) // 聆听中->思考中界面
-            {
-                model->AIVoice_StartTimer();
-            }
             break;
 
         case AIVOICE_THINKING_VIEWID:
@@ -274,23 +332,59 @@ namespace OHOS
             break;
 
         case AIVOICE_RETURN_RESULT_TEXT_VIEWID:
+            // set_need_tts_reconnect(0);                                 // 停止tts重连
             AiVoiceModel::GetInstance().ClearQuestionAndAiAnswerStr(); // 清空上次用户问题和Ai回答字符串
             AiVoiceModel::GetInstance().SetIsClickable(false);
             AiVoiceModel::GetInstance().SetIsLimitDisplayed(false);
-            if (showView == AIVOICE_LISTENING_VIEWID)
-            {
-                model->StartListenAndRecordingUserQuestion();
-            }
+            AiVoiceModel::GetInstance().stop_ai4g_tts_play_timer();
+            AiVoiceModel::GetInstance().stop_update_ai_answer_timer();
+            AiVoiceModel::GetInstance().stop_uapi_stop_tts_timer();
             break;
 
+        case AIVOICE_4GSERVICECON_VIEW:
+            model->stop_ai4g_connect_timer();
+            break;
         default:
             // Handle other cases if needed
             break;
         }
 
+        switch (showView)
+        {
+        case AIVOICE_AIMODE_CONNECTING:
+            model->QuerySelectedAiModelIsConnect();
+            AiVoiceModel::GetInstance().start_ai_isready_timer();
+            break;
+        case AIVOICE_RETURN_RESULT_TEXT_VIEWID:
+            // set_need_tts_reconnect(1); // 开始tts重连
+            break;
+        case AIVOICE_LISTENING_VIEWID:
+            // set_stop_send_ai_flag(0); // 开始发送AI数据
+            AiVoiceModel::GetInstance().StartListenAndRecordingUserQuestion();
+            AiVoiceModel::GetInstance().start_listening_timer();
+            break;
+
+        case AIVOICE_THINKING_VIEWID:
+            AiVoiceModel::GetInstance().AIVoice_StartTimer();
+            break;
+
+        default:
+            break;
+        }
+
         return true;
     }
 
+    void AiVoicePresenter::JumpThinkingView(void)
+    {
+        if ((view_->GetAiVoiceScrollView(AIVOICE_LISTENING_VIEWID) != nullptr) &&
+            (view_->GetAiVoiceScrollView(AIVOICE_LISTENING_VIEWID)->IsVisible()))
+        {
+            ChangeViewAndLogicOperator(AIVOICE_LISTENING_VIEWID, AIVOICE_THINKING_VIEWID);
+        }
+        return;
+    }
+
     // 处理手点击屏幕切换AI模型
     bool AiVoicePresenter::OnClick(UIView &view, const ClickEvent &event)
     {
@@ -314,56 +408,14 @@ namespace OHOS
         return true;
     }
 
-    bool AiVoicePresenter::OnPress(UIView& view, const PressEvent& event)
+    bool AiVoicePresenter::OnPress(UIView &view, const PressEvent &event)
     {
         UNUSED(event);
         std::string viewId = view.GetViewId();
-        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnRelease %s", viewId.c_str());
+        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnPress %s", viewId.c_str());
         /* ----------------------------- 重置60s取消常亮屏timer ---------------------------- */
         model->reset_ai_screen60s_timer_time();
         /* -------------------------------------------------------------------------- */
-        std::unordered_map<std::string, std::pair<int16_t, int16_t>> viewIdMap = {
-            {AIVOICERETURNRESULTTEXT_RETURN_BUTTON_VIEW_ID, {AIVOICE_RETURN_RESULT_TEXT_VIEWID, AIVOICE_STARTCHAT_VIEWID}},                        // 返回一级界面,并清除手表聊天记录
-            {AIVOICERETURNRESULTTEXT_CONTINUECHAT_BUTTON_VIEW_ID, {AIVOICE_RETURN_RESULT_TEXT_VIEWID, AIVOICE_LISTENING_VIEWID}},                  // 返回继续聆听,并清除手表聊天记录
-        };
-        auto it = viewIdMap.find(viewId);
-        if (it != viewIdMap.end())
-        {
-            #if 0
-            if(!model->GetIsClickable())
-            {
-                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "当前还不可点击");
-                return true;
-            }
-            #endif
-            if (it->first == AIVOICERETURNRESULTTEXT_CONTINUECHAT_BUTTON_VIEW_ID) // 点击继续对话按钮要发取消当前对话指令,避免AI回应中途按继续对话按钮没有取消上一次对话问题
-            {
-                WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "CancelCurAIChat");
-                AiVoiceModel::GetInstance().CancelCurAIChat();
-                // AiVoiceModel::GetInstance().sendAIIsReady();
-                PlayersModel::GetInstance()->HandPausePhoneMusic(); // 暂停手机音乐
-                PlayersModel::GetInstance()->PlayerPause();         // 暂停手机音乐
-            }
-            ChangeViewAndLogicOperator(it->second.first, it->second.second);
-            return true;
-        }
-        return true;
-    }
-
-    bool AiVoicePresenter::OnRelease(UIView &view, const ReleaseEvent &event)
-    {
-        UNUSED(event);
-        std::string viewId = view.GetViewId();
-        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnRelease %s", viewId.c_str());
-        /* ----------------------------- 重置60s取消常亮屏timer ---------------------------- */
-        model->reset_ai_screen60s_timer_time();
-        /* -------------------------------------------------------------------------- */
-
-        // if ((viewId == AIVOICE_CHAT_BUTTON_VIEW_ID) && model->IsExistOpenAIAPIKeys() == false) // 如果点击的是(对话按钮)且未配置apikey
-        // {
-        //     ChangeViewAndLogicOperator(AIVOICE_STARTCHAT_VIEWID, AIVOICE_NOTSETAPIKEYS); /*开始对话界面->API Keys notset界面*/
-        //     return true;
-        // }
         if (viewId == AIVOICE_APIKEYS_BUTTON_VIEW_ID) // 如果点击的是API Keys按钮(注:暂时不用)
         {
             if (model->IsExistOpenAIAPIKeys() == true)
@@ -391,53 +443,202 @@ namespace OHOS
             bool appBluetoothConnectState = model->GetAPPBluetoothIsConnect();
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "netWork4GState = %d,appBluetoothConnectState = %d", netWork4GState, appBluetoothConnectState);
 
-            if (netWork4GState) // 1.手表4G网络正常
+            model->SetAI_4G_state(netWork4GState);
+            model->SetAI_BT_state(appBluetoothConnectState);
+            if ((netWork4GState && appBluetoothConnectState))
+            {
+                // 获取用户上次的选择
+                int lastSelectedType = model->GetSelect4gorbt();
+                // 两者都可用,检查是否有上次的选择
+                if (lastSelectedType == AI_SELECT_4G)
+                {
+                    // 使用4G
+                    model->SetSelect4gorbt(AI_SELECT_4G);
+                    if (model->GetAiModelTextId() == STR_AIMODES_CHATGPT) // 如果当前是在chatgpt模型*/
+                    {
+                        ChangeViewAndLogicOperator(model->GetCurView(), AIVOICE_NOTSETAPIKEYS); /*开始对话界面->API Keys notset界面*/
+                        return true;
+                    }
+                    if (!model->GetInit_4gai_task())
+                    {
+                        // init_ai_task(AiVoiceModel::GetInstance().GetCurUsing4GAiModelType());
+                        model->start_ai4g_connect_timer();
+                        ChangeViewAndLogicOperator(AIVOICE_STARTCHAT_VIEWID, AIVOICE_4GSERVICECON_VIEW); // LOADING
+                    }
+                    else
+                    {
+                        ChangeViewAndLogicOperator(AIVOICE_STARTCHAT_VIEWID, AIVOICE_AIMODE_CONNECTING); // LOADING
+                    }
+                }
+                else if (lastSelectedType == AI_SELECT_BT)
+                {
+                    // 使用蓝牙
+                    model->SetSelect4gorbt(AI_SELECT_BT);
+                    ChangeViewAndLogicOperator(AIVOICE_STARTCHAT_VIEWID, AIVOICE_AIMODE_CONNECTING); // LOADING
+                }
+                else
+                {
+                    // 没有上次的选择,让用户选择
+                    ChangeViewAndLogicOperator(AIVOICE_STARTCHAT_VIEWID, AIVOICE_SELECT_VIEW); // LOADING
+                }
+            }
+            else if (netWork4GState) // 1.手表4G网络正常
             {
                 // 通过4G调用大模型
+                model->SetSelect4gorbt(AI_SELECT_4G);
+                if (model->GetAiModelTextId() == STR_AIMODES_CHATGPT) // 如果当前是在chatgpt模型*/
+                {
+                    ChangeViewAndLogicOperator(model->GetCurView(), AIVOICE_NOTSETAPIKEYS); /*开始对话界面->API Keys notset界面*/
+                    return true;
+                }
+                if (!model->GetInit_4gai_task())
+                {
+                    // init_ai_task(AiVoiceModel::GetInstance().GetCurUsing4GAiModelType());
+                    model->start_ai4g_connect_timer();
+                    ChangeViewAndLogicOperator(AIVOICE_STARTCHAT_VIEWID, AIVOICE_4GSERVICECON_VIEW); // LOADING
+                }
+                else
+                {
+                    ChangeViewAndLogicOperator(AIVOICE_STARTCHAT_VIEWID, AIVOICE_AIMODE_CONNECTING); // LOADING
+                }
             }
             else if (appBluetoothConnectState) // 3.只有与APP蓝牙连接正常
             {
                 // 通过蓝牙连接APP调用大模型
+                model->SetSelect4gorbt(AI_SELECT_BT);
                 ChangeViewAndLogicOperator(AIVOICE_STARTCHAT_VIEWID, AIVOICE_AIMODE_CONNECTING); // LOADING
             }
             else // 4.两者连接都异常
             {
                 // 返回错误
+                model->SetSelect4gorbt(AI_SELECT_DEFAULT);
                 ChangeViewAndLogicOperator(AIVOICE_STARTCHAT_VIEWID, AIVOICE_ALERT_APPBLUETOOTH_AND_4GNETWORK_VIEWID);
-                // ChangeViewAndLogicOperator(AIVOICE_STARTCHAT_VIEWID, AIVOICE_AIMODEL_CONNECT_FAILED_VIEWID);
             }
             return true;
         }
         else if (viewId == FINISH_SPEAKING_BUTTON_VIEW_ID) // 如果点击的是说话完毕按钮
         {
-            ChangeViewAndLogicOperator(AIVOICE_LISTENING_VIEWID, AIVOICE_THINKING_VIEWID);
+            if (model->GetSelect4gorbt() == AI_SELECT_4G)
+            {
+#if AI_VOICE_ENABLE
+                uapi_UI_stop_asr();
+#endif
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "FINISH_SPEAKING_BUTTON_VIEW_ID:(%d,%d)", model->is_need_to_jump_result_view(), model->getentryTextViewState());
+                if (!model->is_need_to_jump_result_view() && !model->getentryTextViewState()) // 没有数据就跳转到思考中界面
+                {
+                    GraphicService::GetInstance()->PostGraphicEvent(
+                        std::bind(&OHOS::AiVoicePresenter::JumpThinkingView, OHOS::AiVoicePresenter::GetInstance()));
+                }
+            }
+            else if (model->GetSelect4gorbt() == AI_SELECT_BT)
+            {
+                ChangeViewAndLogicOperator(AIVOICE_LISTENING_VIEWID, AIVOICE_THINKING_VIEWID);
+            }
+            return true;
+        }
+        else if (viewId == AIVOICE_SELECT_VIEW_BUTTON4G_VIEW_ID) // 如果点击的是4G连接方式
+        {
+            // 通过4G调用大模型
+            model->SetSelect4gorbt(AI_SELECT_4G);
+            if (model->GetAiModelTextId() == STR_AIMODES_CHATGPT) // 如果当前是在chatgpt模型*/
+            {
+                ChangeViewAndLogicOperator(model->GetCurView(), AIVOICE_NOTSETAPIKEYS); /*开始对话界面->API Keys notset界面*/
+                return true;
+            }
+            if (!model->GetInit_4gai_task())
+            {
+                // init_ai_task(AiVoiceModel::GetInstance().GetCurUsing4GAiModelType());
+                model->start_ai4g_connect_timer();
+                ChangeViewAndLogicOperator(model->GetCurView(), AIVOICE_4GSERVICECON_VIEW); // LOADING
+            }
+            else
+            {
+                ChangeViewAndLogicOperator(model->GetCurView(), AIVOICE_AIMODE_CONNECTING); // LOADING
+            }
+            return true;
+        }
+        else if (viewId == AIVOICE_SELECT_VIEW_BUTTONBT_VIEW_ID) // 如果点击的是蓝牙连接方式
+        {
+            model->SetSelect4gorbt(AI_SELECT_BT);
+            ChangeViewAndLogicOperator(model->GetCurView(), AIVOICE_AIMODE_CONNECTING);
             return true;
         }
 
         std::unordered_map<std::string, std::pair<int16_t, int16_t>> viewIdMap = {
+            {AIVOICERETURNRESULTTEXT_RETURN_BUTTON_VIEW_ID, {AIVOICE_RETURN_RESULT_TEXT_VIEWID, AIVOICE_STARTCHAT_VIEWID}},       // 返回一级界面,并清除手表聊天记录
+            {AIVOICERETURNRESULTTEXT_CONTINUECHAT_BUTTON_VIEW_ID, {AIVOICE_RETURN_RESULT_TEXT_VIEWID, AIVOICE_LISTENING_VIEWID}}, // 返回继续聆听,并清除手表聊天记录
+        };
+        auto it = viewIdMap.find(viewId);
+        if (it != viewIdMap.end())
+        {
+            if (it->first == AIVOICERETURNRESULTTEXT_CONTINUECHAT_BUTTON_VIEW_ID) // 点击继续对话按钮要发取消当前对话指令,避免AI回应中途按继续对话按钮没有取消上一次对话问题
+            {
+                WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "CancelCurAIChat");
+                PlayersModel::GetInstance()->HandPausePhoneMusic(); // 暂停手机音乐
+                PlayersModel::GetInstance()->PlayerPause();         // 暂停手机音乐
+                if (model->GetSelect4gorbt() == AI_SELECT_4G)
+                {
+                    AiVoiceModel::GetInstance().stop_ai4g_tts_play_timer();
+                    AiVoiceModel::GetInstance().stop_uapi_stop_tts_timer();
+                    // usleep(50000);
+                    set_clear_queue_stream(1);
+                    LOS_Msleep(100);
+                    // uapi_UI_start_asr(AiVoiceModel::GetInstance().GetCurUsing4GAiModelType());
+                    ChangeViewAndLogicOperator(AIVOICE_RETURN_RESULT_TEXT_VIEWID, AIVOICE_AIMODE_CONNECTING);
+                    return true;
+                }
+                else if (model->GetSelect4gorbt() == AI_SELECT_BT)
+                {
+                    AiVoiceModel::GetInstance().CancelCurAIChat();
+                    AiVoiceModel::GetInstance().sendAIIsReady();
+                }
+            }
+            else if (it->first == AIVOICERETURNRESULTTEXT_RETURN_BUTTON_VIEW_ID)
+            {
+                if (model->GetSelect4gorbt() == AI_SELECT_4G)
+                {
+                    AiVoiceModel::GetInstance().stop_ai4g_tts_play_timer();
+                    AiVoiceModel::GetInstance().stop_uapi_stop_tts_timer();
+                    set_clear_queue_stream(1);
+                    LOS_Msleep(100);
+#if AI_VOICE_ENABLE
+                    dinit_ai_task();
+#endif
+                }
+            }
+            ChangeViewAndLogicOperator(it->second.first, it->second.second);
+            return true;
+        }
+
+        std::unordered_map<std::string, std::pair<int16_t, int16_t>> viewIdMap2 = {
             {ALERT_APPBLUETOOTH_AND_4GNETWORK_ENSURE_BUTTON_VIEW_ID, {AIVOICE_ALERT_APPBLUETOOTH_AND_4GNETWORK_VIEWID, AIVOICE_STARTCHAT_VIEWID}}, // 返回一级界面
             {AIMODEL_CONNECT_FAILED_ENSURE_BUTTON_VIEW_ID, {AIVOICE_AIMODEL_CONNECT_FAILED_VIEWID, AIVOICE_STARTCHAT_VIEWID}},                     // 返回一级界面
             {AIVOICECONNECTTIMEOUT_ENSURE_BUTTON_VIEW_ID, {AIVOICE_CONNECT_TIMEOUT_VIEWID, AIVOICE_STARTCHAT_VIEWID}},                             // 返回一级界面
             {CANCEL_THINKING_BUTTON_VIEW_ID, {AIVOICE_THINKING_VIEWID, AIVOICE_STARTCHAT_VIEWID}},                                                 // 返回一级界面
             {AIVOICECONNECTINGVIEW_CANCEL_BUTTON_VIEW_ID, {AIVOICE_AIMODE_CONNECTING, AIVOICE_STARTCHAT_VIEWID}},                                  // 返回一级界面
-            // {AIVOICERETURNRESULTTEXT_RETURN_BUTTON_VIEW_ID, {AIVOICE_RETURN_RESULT_TEXT_VIEWID, AIVOICE_STARTCHAT_VIEWID}},                        // 返回一级界面,并清除手表聊天记录
-            // {AIVOICERETURNRESULTTEXT_CONTINUECHAT_BUTTON_VIEW_ID, {AIVOICE_RETURN_RESULT_TEXT_VIEWID, AIVOICE_LISTENING_VIEWID}},                  // 返回继续聆听,并清除手表聊天记录
         };
-        auto it = viewIdMap.find(viewId);
-        if (it != viewIdMap.end())
+        it = viewIdMap2.find(viewId);
+        if (it != viewIdMap2.end())
         {
-            // if (it->first == AIVOICERETURNRESULTTEXT_CONTINUECHAT_BUTTON_VIEW_ID) // 点击继续对话按钮要发取消当前对话指令,避免AI回应中途按继续对话按钮没有取消上一次对话问题
-            // {
-            //     WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "CancelCurAIChat");
-            //     AiVoiceModel::GetInstance().CancelCurAIChat();
-            //     PlayersModel::GetInstance()->HandPausePhoneMusic(); // 暂停手机音乐
-            //     PlayersModel::GetInstance()->PlayerPause();         // 暂停手机音乐
-            // }
+            if (it->first != ALERT_APPBLUETOOTH_AND_4GNETWORK_ENSURE_BUTTON_VIEW_ID)
+            {
+                if (model->GetSelect4gorbt() == AI_SELECT_4G)
+                {
+#if AI_VOICE_ENABLE
+                    dinit_ai_task();
+#endif
+                    LOS_Msleep(50);
+                }
+            }
             ChangeViewAndLogicOperator(it->second.first, it->second.second);
             return true;
         }
         return true;
     }
+    bool AiVoicePresenter::OnRelease(UIView &view, const ReleaseEvent &event)
+    {
+        return true;
+    }
 
     bool AiVoicePresenter::OnDrag(UIView &view, const DragEvent &event)
     {
@@ -471,7 +672,7 @@ namespace OHOS
             if (scrollView == view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID))
             {
                 /*AI对话界面右滑退出当前Slice*/
-                // NativeAbility::GetInstance().Back();
+                // NativeAbility::GetInstance().Back(TransitionType::TRANSITION_BACK_TO_HEXAGONS);
                 DragLeftToRightChangeAIModel();
             }
             else if (scrollView == view_->GetAiVoiceScrollView(AIVOICE_ALERT_APPBLUETOOTH_AND_4GNETWORK_VIEWID))
@@ -486,11 +687,19 @@ namespace OHOS
             }
             else if (scrollView == view_->GetAiVoiceScrollView(AIVOICE_LISTENING_VIEWID))
             {
+                if (model->GetSelect4gorbt() == AI_SELECT_4G)
+                {
+                    return true;
+                }
                 /*聆听中界面右滑退回到AI对话界面*/
                 ChangeViewAndLogicOperator(AIVOICE_LISTENING_VIEWID, AIVOICE_STARTCHAT_VIEWID);
             }
             else if (scrollView == view_->GetAiVoiceScrollView(AIVOICE_THINKING_VIEWID))
             {
+                if (model->GetSelect4gorbt() == AI_SELECT_4G)
+                {
+                    return true;
+                }
                 /*思考中界面右滑退到AI对话界面*/
                 ChangeViewAndLogicOperator(AIVOICE_THINKING_VIEWID, AIVOICE_STARTCHAT_VIEWID);
             }
@@ -504,6 +713,16 @@ namespace OHOS
                 /*连接超时界面右滑退到AI对话界面*/
                 ChangeViewAndLogicOperator(AIVOICE_AIMODE_CONNECTING, AIVOICE_STARTCHAT_VIEWID);
             }
+            else if (scrollView == view_->GetAiVoiceScrollView(AIVOICE_SELECT_VIEW))
+            {
+                /*连接超时界面右滑退到AI对话界面*/
+                ChangeViewAndLogicOperator(AIVOICE_SELECT_VIEW, AIVOICE_STARTCHAT_VIEWID);
+            }
+            else if (scrollView == view_->GetAiVoiceScrollView(AIVOICE_VOLUME_VIEW))
+            {
+                /*连接超时界面右滑退到AI对话界面*/
+                ChangeViewAndLogicOperator(AIVOICE_VOLUME_VIEW, AIVOICE_STARTCHAT_VIEWID);
+            }
             AiVoicePresenter::X_DRAG_FLAG = false;
         }
         else if (model->GetAiModelTextId() == STR_AIMODES_CHATGPT && event.GetDragDirection() == DragEvent::DIRECTION_BOTTOM_TO_TOP) /*上滑*/
@@ -531,7 +750,10 @@ namespace OHOS
         if (keyID == static_cast<uint16_t>(ZliteKeyCode::ZLITE_KEY_POWER) && keyState == 1 && uapi_get_screen_state() == 0)
         {
             NativeAbility::GetInstance().Back();
-            AiVoiceModel::GetInstance().CancelCurAIChat();
+            if (model->GetSelect4gorbt() == AI_SELECT_BT)
+            {
+                AiVoiceModel::GetInstance().CancelCurAIChat();
+            }
         }
         return true;
     }
@@ -539,7 +761,7 @@ namespace OHOS
     void AiVoicePresenter::OnPickerStoped(UIPicker &picker)
     {
         WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnPickerStoped,%d", picker.GetSelected());
-        if(view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID) && view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID)->IsVisible() == true)
+        if (view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID) && view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID)->IsVisible() == true)
         {
             model->SetSelectAiModel(picker.GetSelected());
             view_->ChangeAiModelAndUpdateComponentsStatus();
@@ -565,23 +787,88 @@ namespace OHOS
         {
             preHeight = label.GetTextHeight();
             isScroll = true;
+            if ((view_->GetAiVoiceScrollView(AIVOICE_RETURN_RESULT_TEXT_VIEWID) != nullptr) &&
+                (view_->GetAiVoiceScrollView(AIVOICE_RETURN_RESULT_TEXT_VIEWID)->IsVisible()))
+            {
+                if (isScroll)
+                {
+                    // 监听,让List实现滚动
+                    AivoiceReturnResultTextView::GetInstance()->GetChatContentList()->ScrollBy(-120);
+                    isScroll = false;
+                }
+            }
         }
         return;
     }
 
-    //监听高度是否变化
-    void AiVoicePresenter::Notify()
+    void AiVoicePresenter::ChangeVolume(UIView &view, const RotateEvent &event)
     {
         if ((view_->GetAiVoiceScrollView(AIVOICE_RETURN_RESULT_TEXT_VIEWID) != nullptr) &&
             (view_->GetAiVoiceScrollView(AIVOICE_RETURN_RESULT_TEXT_VIEWID)->IsVisible()))
         {
-            if (isScroll)
+            UISlider *slider = dynamic_cast<UISlider *>(&view);
+            if (slider)
             {
-                // 监听,让List实现滚动
-                AivoiceReturnResultTextView::GetInstance()->GetChatContentList()->ScrollBy(-120);
-                isScroll = false;
+                int value = slider->GetValue();
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "volume:%d front", value);
+                if (event.GetRotate() <= 0)
+                {
+                    WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "222");
+                    value += 20;
+                    if (value > 100)
+                    {
+                        value = 100;
+                    }
+                }
+                else
+                {
+                    WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "111");
+                    value -= 20;
+                    if (value < 0)
+                    {
+                        value = 0;
+                    }
+                }
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "volume:%d end", value);
+                do_custom_cmd_service_check_msg(CUSTOM_CMD_MSG_TYPE_CHANGE_SYSTEM_VOLUME, (void *)(&value), sizeof(value));
             }
         }
-        return;
+    }
+
+    bool AiVoicePresenter::OnRotate(UIView &view, const RotateEvent &event)
+    {
+        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnRotate");
+        static uint32_t lastCallTime = 0;
+        const uint32_t MIN_INTERVAL = 500; // 最小间隔500ms
+
+        uint32_t currentTime = event.GetTimeStamp();
+
+        // 计算时间间隔
+        uint32_t interval = currentTime - lastCallTime;
+
+        // 仅当间隔大于500ms时才调用ChangeVolume
+        if (interval >= MIN_INTERVAL)
+        {
+            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnRotate: 允许调用ChangeVolume, 间隔: %ums", interval);
+            ChangeVolume(view, event);
+            lastCallTime = currentTime;
+        }
+        else
+        {
+            WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnRotate: 忽略调用ChangeVolume, 间隔: %ums (需要>500ms)", interval);
+        }
+
+        return true;
+    }
+
+    bool AiVoicePresenter::OnRotateEnd(UIView &view, const RotateEvent &event)
+    {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoicePresenter::OnRotateEnd");
+        // if (view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID) && view_->GetAiVoiceScrollView(AIVOICE_STARTCHAT_VIEWID)->IsVisible() == true)
+        // {
+        //     ChangeViewAndLogicOperator(AIVOICE_STARTCHAT_VIEWID, AIVOICE_VOLUME_VIEW);
+        // }
+        ChangeVolume(view, event);
+        return true;
     }
 }
\ No newline at end of file
diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceSelectView.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceSelectView.cpp
new file mode 100644 (file)
index 0000000..934c242
--- /dev/null
@@ -0,0 +1,175 @@
+#include "aivoice/include/AiVoicePresenter.h"
+#include "aivoice/include/AiVoiceSelectView.h"
+#include "wearable_log.h"
+
+namespace OHOS
+{
+    static AiVoiceSelectView *g_pAivoiceSelectView{nullptr};
+    AiVoiceSelectView::AiVoiceSelectView()
+    {
+        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceSelectView::AiVoiceSelectView");
+        g_pAivoiceSelectView = this;
+    }
+    AiVoiceSelectView::~AiVoiceSelectView()
+    {
+        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceSelectView::~AiVoiceSelectView");
+        ClearAll();
+        g_pAivoiceSelectView = nullptr;
+    }
+
+    AiVoiceSelectView *AiVoiceSelectView::GetInstance(void)
+    {
+        return g_pAivoiceSelectView;
+    }
+
+    void AiVoiceSelectView::ClearAll(void)
+    {
+        if (scrollView != nullptr)
+        {
+            scrollView->RemoveAll();
+            delete title;
+            title = nullptr;
+            delete label4g;
+            label4g = nullptr;
+            delete labelbt;
+            labelbt = nullptr;
+            delete button4g;
+            button4g = nullptr;
+            delete buttonbt;
+            buttonbt = nullptr;
+            delete scrollView;
+            scrollView = nullptr;
+        }
+    }
+
+    UIScrollView *AiVoiceSelectView::CreateAiVoiceSelectView(void)
+    {
+        if (scrollView == nullptr)
+        {
+            scrollView = new UIScrollView();
+            if (scrollView == nullptr)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceSelectView::scrollView new fail!");
+                return nullptr;
+            }
+        }
+        scrollView->SetPosition(0, 0, 466, 466);
+        UIView::OnDragListener *dragListener = static_cast<UIView::OnDragListener *>(AiVoicePresenter::GetInstance());
+        if (dragListener == nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceSelectView::dragListener new fail!");
+            return nullptr;
+        }
+        scrollView->SetOnDragListener(dragListener);
+        scrollView->SetTouchable(true);
+        scrollView->SetDraggable(true);
+        /* -------------------------------------------------------------------------- */
+        if (title == nullptr)
+        {
+            title = new UILabelExt();
+            if (title == nullptr)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceSelectView::title new fail!");
+                return nullptr;
+            }
+        }
+        title->SetPosition(83, 50, 300, 35);
+        title->SetStyle(STYLE_TEXT_FONT, 30);
+        title->SetStyle(STYLE_LINE_HEIGHT, 35);
+        title->SetText("AI对话");
+        title->SetLineBreakMode(UILabel::LINE_BREAK_OSCILLATION);
+        title->SetRollSpeed(23);
+        title->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER);
+        title->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 30);
+        scrollView->Add(title);
+        /* -------------------------------------------------------------------------- */
+        int y1 = 123;
+        if (label4g == nullptr)
+        {
+            label4g = new UILabelExt();
+            if (label4g == nullptr)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceSelectView::title new fail!");
+                return nullptr;
+            }
+        }
+        label4g->SetPosition(83, y1 + 33, 300, 35);
+        label4g->SetStyle(STYLE_TEXT_FONT, 30);
+        label4g->SetStyle(STYLE_LINE_HEIGHT, 35);
+        label4g->SetText("4G连接");
+        label4g->SetLineBreakMode(UILabel::LINE_BREAK_OSCILLATION);
+        label4g->SetRollSpeed(23);
+        label4g->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER);
+        label4g->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 30);
+        /* -------------------------------------------------------------------------- */
+        int y2 = 243;
+        if (labelbt == nullptr)
+        {
+            labelbt = new UILabelExt();
+            if (labelbt == nullptr)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceSelectView::title new fail!");
+                return nullptr;
+            }
+        }
+        labelbt->SetPosition(83, y2 + 33, 300, 35);
+        labelbt->SetStyle(STYLE_TEXT_FONT, 30);
+        labelbt->SetStyle(STYLE_LINE_HEIGHT, 35);
+        labelbt->SetText("蓝牙连接");
+        labelbt->SetLineBreakMode(UILabel::LINE_BREAK_OSCILLATION);
+        labelbt->SetRollSpeed(23);
+        labelbt->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER);
+        labelbt->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 30);
+        /* -------------------------------------------------------------------------- */
+        if (button4g == nullptr)
+        {
+            button4g = new UIButton();
+            if (button4g == nullptr)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceSelectView::title new fail!");
+                return nullptr;
+            }
+        }
+        button4g->SetPosition(43, 123, 380, 100);
+        button4g->SetViewId(AIVOICE_SELECT_VIEW_BUTTON4G_VIEW_ID);
+        button4g->SetStyle(STYLE_BACKGROUND_COLOR, 0xff191919);
+        button4g->SetStyle(STYLE_BACKGROUND_OPA, 0xff);
+        button4g->SetStyleForState(STYLE_BACKGROUND_COLOR, 0xff383838, UIButton::PRESSED);
+        UIView::OnTouchListener *listener4g = static_cast<UIView::OnTouchListener *>(AiVoicePresenter::GetInstance());
+        if (listener4g == nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceSelectView::listener4g new fail!");
+            return nullptr;
+        }
+        button4g->SetOnTouchListener(listener4g);
+        /* -------------------------------------------------------------------------- */
+        if (buttonbt == nullptr)
+        {
+            buttonbt = new UIButton();
+            if (buttonbt == nullptr)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceSelectView::title new fail!");
+                return nullptr;
+            }
+        }
+        buttonbt->SetPosition(43, 243, 380, 100);
+        buttonbt->SetViewId(AIVOICE_SELECT_VIEW_BUTTONBT_VIEW_ID);
+        buttonbt->SetStyle(STYLE_BACKGROUND_COLOR, 0xff191919);
+        buttonbt->SetStyle(STYLE_BACKGROUND_OPA, 0xff);
+        buttonbt->SetStyleForState(STYLE_BACKGROUND_COLOR, 0xff383838, UIButton::PRESSED);
+        UIView::OnTouchListener *listenerbt = static_cast<UIView::OnTouchListener *>(AiVoicePresenter::GetInstance());
+        if (listenerbt == nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceSelectView::listenerbt new fail!");
+            return nullptr;
+        }
+        buttonbt->SetOnTouchListener(listenerbt);
+
+        scrollView->Add(button4g);
+        scrollView->Add(buttonbt);
+        scrollView->Add(label4g);
+        scrollView->Add(labelbt);
+
+        return scrollView;
+    }
+}
\ No newline at end of file
index 5ee1d28..bcf2d91 100644 (file)
@@ -34,112 +34,136 @@ namespace OHOS
         return g_pAiVoiceView;
     }
 
-    void AiVoiceView::ClearAll(void)
+    void AiVoiceView::ClearAllAiVoiceScrollView(void)
     {
-        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceView::ClearAll");
-        if (viewInitStatus)
+        if (scrollView != nullptr)
         {
-           
+            scrollView->RemoveAll();
+            delete scrollView;
+            scrollView = nullptr;
 
-            if (AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID] != nullptr)
-            {
-                AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->RemoveAll();
+            delete VolumeProcess;
+            VolumeProcess = nullptr;
 
-                delete title;
-                title = nullptr;
+            delete title;
+            title = nullptr;
 
-                delete aiModelImage;
-                aiModelImage = nullptr;
+            delete aiModelImage;
+            aiModelImage = nullptr;
 
-                delete startChatButton;
-                startChatButton = nullptr;
+            delete startChatButton;
+            startChatButton = nullptr;
 
-                delete startChatLabel;
-                startChatLabel = nullptr;
+            delete startChatLabel;
+            startChatLabel = nullptr;
 
-                delete chatButton;
-                chatButton = nullptr;
+            delete chatButton;
+            chatButton = nullptr;
 
-                delete chatLabel;
-                chatLabel = nullptr;
+            delete chatLabel;
+            chatLabel = nullptr;
 
-                delete apiKeysLabel;
-                apiKeysLabel = nullptr;
+            delete apiKeysLabel;
+            apiKeysLabel = nullptr;
 
-                delete apiKeysButton;
-                apiKeysButton = nullptr;
+            delete apiKeysButton;
+            apiKeysButton = nullptr;
 
-                delete aiModelPicker;
-                aiModelPicker = nullptr;
+            delete aiModelPicker;
+            aiModelPicker = nullptr;
 
-                delete buttonBgImage;
-                buttonBgImage = nullptr;
+            delete buttonBgImage;
+            buttonBgImage = nullptr;
 
-                delete upImage;
-                upImage = nullptr;
+            delete upImage;
+            upImage = nullptr;
+        }
+    }
 
-                delete AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID];
-                AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID] = nullptr;
-            }
+    void AiVoiceView::ClearAll(void)
+    {
+        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceView::ClearAll");
+        ClearAllAiVoiceScrollView();
 
-            if (p_AiVoiceBluetoothFailedStartView != nullptr)
-            {
-                delete p_AiVoiceBluetoothFailedStartView;
-                p_AiVoiceBluetoothFailedStartView = nullptr;
-            }
+        if (p_AiVoiceBluetoothFailedStartView != nullptr)
+        {
+            delete p_AiVoiceBluetoothFailedStartView;
+            p_AiVoiceBluetoothFailedStartView = nullptr;
+        }
 
-            if (p_AivoiceMobileDataFailedStartView != nullptr)
-            {
-                delete p_AivoiceMobileDataFailedStartView;
-                p_AivoiceMobileDataFailedStartView = nullptr;
-            }
+        if (p_AivoiceMobileDataFailedStartView != nullptr)
+        {
+            delete p_AivoiceMobileDataFailedStartView;
+            p_AivoiceMobileDataFailedStartView = nullptr;
+        }
 
-            if (p_AivoiceConnectTimeoutView != nullptr)
-            {
-                delete p_AivoiceConnectTimeoutView;
-                p_AivoiceConnectTimeoutView = nullptr;
-            }
+        if (p_AivoiceConnectTimeoutView != nullptr)
+        {
+            delete p_AivoiceConnectTimeoutView;
+            p_AivoiceConnectTimeoutView = nullptr;
+        }
 
-            if (p_AivoiceListeningView != nullptr)
-            {
-                delete p_AivoiceListeningView;
-                p_AivoiceListeningView = nullptr;
-            }
+        if (p_AivoiceListeningView != nullptr)
+        {
+            delete p_AivoiceListeningView;
+            p_AivoiceListeningView = nullptr;
+        }
 
-            if (p_AivoiceThinkingView != nullptr)
-            {
-                delete p_AivoiceThinkingView;
-                p_AivoiceThinkingView = nullptr;
-            }
+        if (p_AivoiceThinkingView != nullptr)
+        {
+            delete p_AivoiceThinkingView;
+            p_AivoiceThinkingView = nullptr;
+        }
 
-            if (p_AivoiceReturnResultTextView != nullptr)
-            {
-                delete p_AivoiceReturnResultTextView;
-                p_AivoiceReturnResultTextView = nullptr;
-            }
+        if (p_AivoiceReturnResultTextView != nullptr)
+        {
+            delete p_AivoiceReturnResultTextView;
+            p_AivoiceReturnResultTextView = nullptr;
+        }
 
-            if (p_SetApiKeysView != nullptr)
-            {
-                delete p_SetApiKeysView;
-                p_SetApiKeysView = nullptr;
-            }
+        if (p_SetApiKeysView != nullptr)
+        {
+            delete p_SetApiKeysView;
+            p_SetApiKeysView = nullptr;
+        }
 
-            if (p_NotSetApiKeysView != nullptr)
-            {
-                delete p_NotSetApiKeysView;
-                p_NotSetApiKeysView = nullptr;
-            }
+        if (p_NotSetApiKeysView != nullptr)
+        {
+            delete p_NotSetApiKeysView;
+            p_NotSetApiKeysView = nullptr;
+        }
 
-            if (p_ApiKeysDeleteView != nullptr)
-            {
-                delete p_ApiKeysDeleteView;
-                p_ApiKeysDeleteView = nullptr;
-            }
+        if (p_ApiKeysDeleteView != nullptr)
+        {
+            delete p_ApiKeysDeleteView;
+            p_ApiKeysDeleteView = nullptr;
+        }
 
-            if (p_AiVoiceConnectingView != nullptr)
+        if (p_AiVoiceConnectingView != nullptr)
+        {
+            delete p_AiVoiceConnectingView;
+            p_AiVoiceConnectingView = nullptr;
+        }
+        if (p_AiVoiceSelectView != nullptr)
+        {
+            delete p_AiVoiceSelectView;
+            p_AiVoiceSelectView = nullptr;
+        }
+        if (p_Aivoice4gServiceConView != nullptr)
+        {
+            delete p_Aivoice4gServiceConView;
+            p_Aivoice4gServiceConView = nullptr;
+        }
+        if (p_AiVoiceVolumeView)
+        {
+            delete p_AiVoiceVolumeView;
+            p_AiVoiceVolumeView = nullptr;
+        }
+        for (int i = 0; i < MAX_AIVOICE_VIEWID; i++)
+        {
+            if (AiVoiceScrollView[i] != nullptr)
             {
-                delete p_AiVoiceConnectingView;
-                p_AiVoiceConnectingView = nullptr;
+                AiVoiceScrollView[i] = nullptr;
             }
         }
     }
@@ -402,8 +426,11 @@ namespace OHOS
             aiModelPicker->SetStyle(STYLE_BORDER_RADIUS, 150);
             aiModelPicker->SetItemHeight(40);
             aiModelPicker->SetLoopState(true);
+#if defined(AI_VOICE_FD230) || defined(AI_VOICE_N9)
+#else
             aiModelPicker->SetRotateFactor(1.0);
             aiModelPicker->RequestFocus();
+#endif
             aiModelPicker->RegisterSelectedListener(presenter_);
             // 设置文本颜色为透明
             aiModelPicker->SetTextColor(Color::GetColorFromRGBA(0xff, 0xff, 0xff, 0x00), Color::GetColorFromRGBA(0xff, 0xff, 0xff, 0x00));
@@ -418,53 +445,86 @@ namespace OHOS
     bool AiVoiceView::CreateAiVoiceScrollView(void)
     {
         WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceView::CreateAiVoiceScrollView");
-        AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID] = new UIScrollView();
-        if (AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID] == nullptr)
+        if (scrollView == nullptr)
         {
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceView::CreateAiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID] new fail!");
-            return false;
+            scrollView = new UIScrollView();
+            if (scrollView == nullptr)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceView::CreateAiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID] new fail!");
+                return false;
+            }
         }
-        AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->SetPosition(0, 0, 466, 466);
-        AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->SetTouchable(true);
-        AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->SetDraggable(true);
-        AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->SetOnDragListener(presenter_);
-        AddViewToRootContainer(AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]);
+        scrollView->SetPosition(0, 0, 466, 466);
+        scrollView->SetHorizontalScrollState(false);
+        scrollView->SetVerticalScrollState(false);
+        scrollView->SetTouchable(true);
+        scrollView->SetDraggable(true);
+        scrollView->SetOnDragListener(presenter_);
+        return true;
+    }
 
+    bool AiVoiceView::CreateAiVoiceVoiceView(void)
+    {
+        /* ------------------------------ VolumeProcess ----------------------------- */
+        if (VolumeProcess == nullptr)
+        {
+            VolumeProcess = new UISlider();
+            if (VolumeProcess == nullptr)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "VolumeProcess new fail");
+                return false;
+            }
+            VolumeProcess->SetSliderColor(Color::Gray(), Color::Silver());
+            VolumeProcess->SetPosition(-200, 77, 130, 310);
+            VolumeProcess->SetDirection(UISlider::Direction::DIR_BOTTOM_TO_TOP);
+            VolumeProcess->SetRange(100, 0);
+            VolumeProcess->SetStyle(STYLE_BORDER_RADIUS, 100);
+            VolumeProcess->SetBackgroundStyle(STYLE_LINE_CAP, CapType::CAP_ROUND);
+            VolumeProcess->SetForegroundStyle(STYLE_LINE_CAP, CapType::CAP_ROUND);
+            VolumeProcess->SetSliderColor(Color::GetColorFromRGBA(0x19, 0x19, 0x19, 0xff), Color::GetColorFromRGBA(0xff, 0xff, 0xff, 0xff));
+            VolumeProcess->SetForegroundStyle(STYLE_BACKGROUND_OPA, 0xff);
+            VolumeProcess->SetKnobStyle(StyleDefault::GetSliderKnobStyle());
+            VolumeProcess->RequestFocus();
+            VolumeProcess->SetRotateFactor(5.0);
+            // VolumeProcess->SetVisible(false);
+            VolumeProcess->SetOnRotateListener(presenter_);
+            AddViewToRootContainer(VolumeProcess);
+        }
         return true;
     }
 
-    void AiVoiceView::CreateAiVoiceView(void)
+    UIScrollView *AiVoiceView::CreateAiVoiceView(void)
     {
         WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceView::CreateAiVoiceView");
         if (!CreateAiVoiceScrollView() || !CreateAiVoiceViewImageView() || !CreateAiVoiceViewPicker() ||
-            !CreateAiVoiceViewLabel() || !CreateAiVoiceViewButton())
+            !CreateAiVoiceViewLabel() || !CreateAiVoiceViewButton() || !CreateAiVoiceVoiceView())
         {
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceView::CreateAiVoiceView fail!");
-            return;
+            return nullptr;
         }
-        AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->Add(title);
-        AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->Add(aiModelPicker);
-        AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->Add(aiModelImage);
-        AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->Add(startChatButton);
-        AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->Add(startChatLabel);
-        AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->Add(chatButton);
-        AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->Add(chatLabel);
-        AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->Add(apiKeysButton);
-        AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->Add(apiKeysLabel);
-        AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->Add(buttonBgImage);
-        AiVoiceScrollView[AIVOICE_STARTCHAT_VIEWID]->Add(upImage);
+        // scrollView->Add(VolumeProcess);
+        scrollView->Add(title);
+        scrollView->Add(aiModelPicker);
+        scrollView->Add(aiModelImage);
+        scrollView->Add(startChatButton);
+        scrollView->Add(startChatLabel);
+        scrollView->Add(chatButton);
+        scrollView->Add(chatLabel);
+        scrollView->Add(apiKeysButton);
+        scrollView->Add(apiKeysLabel);
+        scrollView->Add(buttonBgImage);
+        scrollView->Add(upImage);
+
+        return scrollView;
     }
 
     void AiVoiceView::OnStart()
     {
         WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceView::OnStart");
-       
-
-        if (!viewInitStatus)
-        {
-            CreateAiVoiceView();
-            viewInitStatus = true;
-        }
+        ChangeView(MAX_AIVOICE_VIEWID, AIVOICE_STARTCHAT_VIEWID);
+#if defined(AI_VOICE_FD230) || defined(AI_VOICE_N9)
+        CreateAiVoiceVoiceView();
+#endif
 
         SetAiVoiceViewAllComponentsVisibilityStatus();
 
@@ -480,9 +540,26 @@ namespace OHOS
         WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceView::ChangeAiVoiceStartChatView");
         if (AiVoiceScrollView[thisView] == nullptr)
         {
+            UIScrollView *scrollview = CreateAiVoiceView();
+            if (scrollview == nullptr)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "new AiVoiceScrollView[%d] fail", thisView);
+                return false;
+            }
+            AiVoiceScrollView[thisView] = scrollview;
             AddViewToRootContainer(AiVoiceScrollView[thisView]);
         }
-        AiVoiceModel::GetInstance().CancelCurAIChat();
+        else
+        {
+            if (VolumeProcess)
+            {
+                VolumeProcess->RequestFocus();
+            }
+        }
+        if (AiVoiceModel::GetInstance().GetSelect4gorbt() == AI_SELECT_BT)
+        {
+            AiVoiceModel::GetInstance().CancelCurAIChat();
+        }
         return true;
     }
 
@@ -586,10 +663,10 @@ namespace OHOS
         }
         if (p_AivoiceListeningView)
         {
+            p_AivoiceListeningView->StartOrStopAivoiceListeningImageAnimatorView(true);
             p_AivoiceListeningView->GetShowtimeoutLabel()->SetText("10");
             p_AivoiceListeningView->GetShowtimeoutLabel()->Invalidate();
         }
-        AiVoiceModel::GetInstance().start_listening_timer();
         return true;
     }
 
@@ -615,6 +692,10 @@ namespace OHOS
             AiVoiceScrollView[thisView] = scrollview;
             AddViewToRootContainer(AiVoiceScrollView[thisView]);
         }
+        if (p_AivoiceThinkingView)
+        {
+            p_AivoiceThinkingView->StartOrStopAiVoiceThinkingImageAnimatorView(true);
+        }
         return true;
     }
 
@@ -624,6 +705,7 @@ namespace OHOS
         WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceView::ChangeAiVoicReturnResultTextView");
         if (AiVoiceScrollView[thisView] == nullptr)
         {
+            AiVoiceModel::GetInstance().SetChatContentListCount(0);
             p_AivoiceReturnResultTextView = new AivoiceReturnResultTextView();
             if (p_AivoiceReturnResultTextView == nullptr)
             {
@@ -743,6 +825,75 @@ namespace OHOS
         return true;
     }
 
+    bool AiVoiceView::ChangeAiVoicSelectView(int16_t thisView)
+    {
+        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceView::ChangeAiVoicSelectView");
+        if (AiVoiceScrollView[thisView] == nullptr)
+        {
+            p_AiVoiceSelectView = new AiVoiceSelectView();
+            if (p_AiVoiceSelectView == nullptr)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "new AiVoiceScrollView[%d] fail", thisView);
+                return false;
+            }
+            UIScrollView *scrollview = p_AiVoiceSelectView->CreateAiVoiceSelectView();
+            if (scrollview == nullptr)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "new AiVoiceScrollView[%d] fail", thisView);
+                return false;
+            }
+            AiVoiceScrollView[thisView] = scrollview;
+            AddViewToRootContainer(AiVoiceScrollView[thisView]);
+        }
+        return true;
+    }
+
+    bool AiVoiceView::ChangeAiVoic4gServiceConView(int16_t thisView)
+    {
+        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceView::ChangeAiVoic4gServiceConView");
+        if (AiVoiceScrollView[thisView] == nullptr)
+        {
+            p_Aivoice4gServiceConView = new AiVoice4gServiceConView();
+            if (p_Aivoice4gServiceConView == nullptr)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "new AiVoiceScrollView[%d] fail", thisView);
+                return false;
+            }
+            UIScrollView *scrollview = p_Aivoice4gServiceConView->CreateAiVoice4gServiceConView();
+            if (scrollview == nullptr)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "new AiVoiceScrollView[%d] fail", thisView);
+                return false;
+            }
+            AiVoiceScrollView[thisView] = scrollview;
+            AddViewToRootContainer(AiVoiceScrollView[thisView]);
+        }
+        return true;
+    }
+
+    bool AiVoiceView::ChangeAiVoicVolumeView(int16_t thisView)
+    {
+        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceView::ChangeAiVoic4gServiceConView");
+        if (AiVoiceScrollView[thisView] == nullptr)
+        {
+            p_AiVoiceVolumeView = new AiVoiceVolumeView();
+            if (p_AiVoiceVolumeView == nullptr)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "new AiVoiceScrollView[%d] fail", thisView);
+                return false;
+            }
+            UIScrollView *scrollview = p_AiVoiceVolumeView->CreateAiVoiceVolumeView();
+            if (scrollview == nullptr)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "new AiVoiceScrollView[%d] fail", thisView);
+                return false;
+            }
+            AiVoiceScrollView[thisView] = scrollview;
+            AddViewToRootContainer(AiVoiceScrollView[thisView]);
+        }
+        return true;
+    }
+
     struct AiVoiceViewMapper
     {
         const int16_t viewId;
@@ -761,6 +912,9 @@ namespace OHOS
         {AIVOICE_NOTSETAPIKEYS, &AiVoiceView::ChangeAiVoicNotSetApiKeysView},
         {AIVOICE_APIKEYS_DELETE, &AiVoiceView::ChangeAiVoicApiKeysDeleteView},
         {AIVOICE_AIMODE_CONNECTING, &AiVoiceView::ChangeAiVoicConnectingView},
+        {AIVOICE_SELECT_VIEW, &AiVoiceView::ChangeAiVoicSelectView},
+        {AIVOICE_4GSERVICECON_VIEW, &AiVoiceView::ChangeAiVoic4gServiceConView},
+        {AIVOICE_VOLUME_VIEW, &AiVoiceView::ChangeAiVoicVolumeView},
     };
 
     bool AiVoiceView::ClickFunc(int16_t interface)
@@ -791,7 +945,7 @@ namespace OHOS
             return false;
         }
 
-        if (hideView < 0 || hideView >= MAX_AIVOICE_VIEWID)
+        if (hideView < 0 || hideView > MAX_AIVOICE_VIEWID)
         {
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceView::CheckViewParam hideView err.");
             return false;
@@ -802,6 +956,16 @@ namespace OHOS
 
     static const int16 AiVoiceDestroyMapper[] = {
         AIVOICE_AIMODE_CONNECTING,
+        AIVOICE_4GSERVICECON_VIEW,
+        AIVOICE_LISTENING_VIEWID,
+        AIVOICE_THINKING_VIEWID,
+        AIVOICE_SELECT_VIEW,
+        AIVOICE_CONNECT_TIMEOUT_VIEWID,
+        AIVOICE_AIMODEL_CONNECT_FAILED_VIEWID,
+        AIVOICE_ALERT_APPBLUETOOTH_AND_4GNETWORK_VIEWID,
+        // AIVOICE_STARTCHAT_VIEWID,
+        AIVOICE_RETURN_RESULT_TEXT_VIEWID,
+        AIVOICE_VOLUME_VIEW,
     };
 
     void AiVoiceView::DestroyTempView(int16_t hideView)
@@ -828,6 +992,77 @@ namespace OHOS
                 p_AiVoiceConnectingView = nullptr;
             }
             break;
+        case AIVOICE_4GSERVICECON_VIEW:
+            if (p_Aivoice4gServiceConView)
+            {
+                delete p_Aivoice4gServiceConView;
+                p_Aivoice4gServiceConView = nullptr;
+            }
+            break;
+        case AIVOICE_LISTENING_VIEWID:
+            if (p_AivoiceListeningView)
+            {
+                if (p_AivoiceListeningView)
+                {
+                    delete p_AivoiceListeningView;
+                    p_AivoiceListeningView = nullptr;
+                }
+                // p_AivoiceListeningView->StartOrStopAivoiceListeningImageAnimatorView(false);
+            }
+            break;
+        case AIVOICE_THINKING_VIEWID:
+            if (p_AivoiceThinkingView)
+            {
+                delete p_AivoiceThinkingView;
+                p_AivoiceThinkingView = nullptr;
+                // p_AivoiceThinkingView->StartOrStopAiVoiceThinkingImageAnimatorView(false);
+            }
+            break;
+        case AIVOICE_SELECT_VIEW:
+            if (p_AiVoiceSelectView)
+            {
+                delete p_AiVoiceSelectView;
+                p_AiVoiceSelectView = nullptr;
+            }
+            break;
+        case AIVOICE_CONNECT_TIMEOUT_VIEWID:
+            if (p_AivoiceConnectTimeoutView)
+            {
+                delete p_AivoiceConnectTimeoutView;
+                p_AivoiceConnectTimeoutView = nullptr;
+            }
+            break;
+        case AIVOICE_AIMODEL_CONNECT_FAILED_VIEWID:
+            if (p_AivoiceMobileDataFailedStartView)
+            {
+                delete p_AivoiceMobileDataFailedStartView;
+                p_AivoiceMobileDataFailedStartView = nullptr;
+            }
+            break;
+        case AIVOICE_ALERT_APPBLUETOOTH_AND_4GNETWORK_VIEWID:
+            if (p_AiVoiceBluetoothFailedStartView)
+            {
+                delete p_AiVoiceBluetoothFailedStartView;
+                p_AiVoiceBluetoothFailedStartView = nullptr;
+            }
+            break;
+        case AIVOICE_STARTCHAT_VIEWID:
+            // ClearAllAiVoiceScrollView();
+            break;
+        case AIVOICE_RETURN_RESULT_TEXT_VIEWID:
+            if (p_AivoiceReturnResultTextView)
+            {
+                delete p_AivoiceReturnResultTextView;
+                p_AivoiceReturnResultTextView = nullptr;
+            }
+            break;
+        case AIVOICE_VOLUME_VIEW:
+            if (p_AiVoiceVolumeView)
+            {
+                delete p_AiVoiceVolumeView;
+                p_AiVoiceVolumeView = nullptr;
+            }
+            break;
         default:
             break;
         }
@@ -835,15 +1070,22 @@ namespace OHOS
 
     void AiVoiceView::ChangeView(int16_t hideView, int16_t showView)
     {
-        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceView::ChangeView");
+        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AiVoiceView::ChangeView hideView:%d, showView:%d", hideView, showView);
         if (!CheckViewParam(hideView, showView))
         {
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceView::CheckViewParam failed.");
             return;
         }
-        AiVoiceScrollView[hideView]->SetVisible(false);
+        if (hideView != MAX_AIVOICE_VIEWID)
+        {
+            if (AiVoiceScrollView[hideView] == nullptr)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceScrollView[%d] is nullptr", hideView);
+                return;
+            }
+            AiVoiceScrollView[hideView]->SetVisible(false);
+        }
         ClickFunc(showView);
-        AiVoiceScrollView[showView]->SetVisible(true);
         if (AiVoiceScrollView[showView] != nullptr)
         {
             AiVoiceScrollView[showView]->SetVisible(true);
diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceVolumeView.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/AiVoiceVolumeView.cpp
new file mode 100644 (file)
index 0000000..8131719
--- /dev/null
@@ -0,0 +1,77 @@
+#include "aivoice/include/AiVoiceVolumeView.h"
+#include "aivoice/include/AiVoicePresenter.h"
+#include "wearable_log.h"
+#include <custom_utils.h>
+namespace OHOS
+{
+    static AiVoiceVolumeView *g_pAiVoiceVolumeView{nullptr};
+    AiVoiceVolumeView::AiVoiceVolumeView()
+    {
+        g_pAiVoiceVolumeView = this;
+    }
+
+    AiVoiceVolumeView::~AiVoiceVolumeView()
+    {
+        ClearAll();
+        g_pAiVoiceVolumeView = nullptr;
+    }
+
+    AiVoiceVolumeView *AiVoiceVolumeView::GetInstance(void)
+    {
+        return g_pAiVoiceVolumeView;
+    }
+
+    void AiVoiceVolumeView::ClearAll()
+    {
+        delete p_SoundAndVibrationVolumeSettingView;
+        p_SoundAndVibrationVolumeSettingView = nullptr;
+        SystemVolumeScrollView = nullptr;
+        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "SystemVolumeView::ClearAll end!!");
+    }
+    void AiVoiceVolumeView::SetRequestFocus()
+    {
+        if (p_SoundAndVibrationVolumeSettingView->GetVolumeProcess())
+        {
+            p_SoundAndVibrationVolumeSettingView->GetVolumeProcess()->RequestFocus();
+        }
+    }
+
+    UIScrollView *AiVoiceVolumeView::CreateAiVoiceVolumeView(void)
+    {
+        if (p_SoundAndVibrationVolumeSettingView == nullptr)
+        {
+            p_SoundAndVibrationVolumeSettingView = new SoundAndVibrationVolumeSettingView(SYSTEM_VOLUME);
+            if (p_SoundAndVibrationVolumeSettingView == nullptr)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "p_SoundAndVibrationVolumeSettingView is nullptr!");
+                return nullptr;
+            }
+        }
+        if (SystemVolumeScrollView == nullptr)
+        {
+            SystemVolumeScrollView = p_SoundAndVibrationVolumeSettingView->SetUpVolumeProcess();
+            if (SystemVolumeScrollView == nullptr)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "SystemVolumeScrollView is nullptr!");
+                return nullptr;
+            }
+        }
+
+        SetRequestFocus();
+
+        int SystemVolume = uapi_systemVolumeGet();
+        WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "SystemVolume = %d", SystemVolume);
+        p_SoundAndVibrationVolumeSettingView->GetVolumeProcess()->SetValue(SystemVolume);
+
+        UIView::OnDragListener *dragListener = static_cast<UIView::OnDragListener *>(AiVoicePresenter::GetInstance());
+        if (dragListener == nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AivoiceThinkingView::dragListener new fail!");
+            return nullptr;
+        }
+        SystemVolumeScrollView->SetOnDragListener(dragListener);
+
+        return SystemVolumeScrollView;
+    }
+
+}
\ No newline at end of file
diff --git a/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/Aivoice4gServiceConView.cpp b/code/sdk/application/wearable/fd230/nativeapp/nativeui/aivoice/src/Aivoice4gServiceConView.cpp
new file mode 100644 (file)
index 0000000..f51a412
--- /dev/null
@@ -0,0 +1,134 @@
+#include "aivoice/include/Aivoice4gServiceConView.h"
+#include "aivoice/include/AiVoicePresenter.h"
+#include "wearable_log.h"
+#include "common/image_cache_manager.h"
+#include "UiConfig.h"
+namespace OHOS
+{
+    static const int16_t AI4GANILABEL_X_FIRST = 83;
+    static const int16_t AI4GANILABEL_Y_FIRST = 257;
+    static const int16_t AI4GANILABEL_WIDTH_FIRST = 300;
+    static const int16_t AI4GANILABEL_HEIGHT_FIRST = 48;
+    static const char *AI4GANILABEL_TEXT_FIRST = (char *)"服务器连接中";
+    static const int16_t AI4GANILABEL_FONT_FIRST = 38;
+
+    const char *AI4GsearchImagePath[] = {
+        PNG_A019_080_IMAGE_PATH,
+        PNG_A019_081_IMAGE_PATH,
+        PNG_A019_082_IMAGE_PATH,
+        PNG_A019_083_IMAGE_PATH,
+        PNG_A019_084_IMAGE_PATH,
+        PNG_A019_085_IMAGE_PATH,
+        PNG_A019_086_IMAGE_PATH,
+        PNG_A019_087_IMAGE_PATH,
+    };
+
+    static const int16_t AI4GALIPAY_BIND_IMAGE_X = 162;
+    static const int16_t AI4GALIPAY_BIND_IMAGE_Y = 112;
+    static const int16_t AI4GALIPAY_BIND_IMAGE_WIDTH = 128;
+    static const int16_t AI4GALIPAY_BIND_IMAGE_HEIGHT = 128;
+    static const int16_t AI4GALIPAY_BIND_IMAGE_DELAY = 100;
+
+    static AiVoice4gServiceConView *g_pAiVoice4gServiceConView{nullptr};
+    AiVoice4gServiceConView::AiVoice4gServiceConView()
+    {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoice4gServiceConView::AiVoice4gServiceConView");
+        g_pAiVoice4gServiceConView = this;
+    }
+
+    AiVoice4gServiceConView::~AiVoice4gServiceConView()
+    {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoice4gServiceConView::~AiVoice4gServiceConView");
+        ClearAll();
+        g_pAiVoice4gServiceConView = nullptr;
+    }
+
+    AiVoice4gServiceConView *AiVoice4gServiceConView::GetInstance(void)
+    {
+        return g_pAiVoice4gServiceConView;
+    }
+
+    void AiVoice4gServiceConView::ClearAll(void)
+    {
+        if (scrollView != nullptr)
+        {
+            scrollView->RemoveAll();
+            delete label;
+            label = nullptr;
+            if (AI4GImageAni)
+            {
+                AI4GImageAni->Stop();
+                delete AI4GImageAni;
+                AI4GImageAni = nullptr;
+                for (int i = 0; i < 8; i++)
+                {
+                    ImageCacheManager::GetInstance().UnloadSingleRes(AI4GsearchImagePath[i]);
+                }
+            }
+            delete scrollView;
+            scrollView = nullptr;
+        }
+    }
+
+    UIScrollView *AiVoice4gServiceConView::CreateAiVoice4gServiceConView(void)
+    {
+        if (scrollView == nullptr)
+        {
+            scrollView = new UIScrollView();
+            if (scrollView == nullptr)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceSelectView::scrollView new fail!");
+                return nullptr;
+            }
+        }
+        scrollView->SetPosition(0, 0, 466, 466);
+        UIView::OnDragListener *dragListener = static_cast<UIView::OnDragListener *>(AiVoicePresenter::GetInstance());
+        if (dragListener == nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceSelectView::dragListener new fail!");
+            return nullptr;
+        }
+        scrollView->SetOnDragListener(dragListener);
+        scrollView->SetTouchable(true);
+        scrollView->SetDraggable(true);
+        /* -------------------------------------------------------------------------- */
+        label = new UILabelExt();
+        if (label == nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AlipayBindAni::InitExit new label fail");
+            return nullptr;
+        }
+        label->SetPosition(AI4GANILABEL_X_FIRST, AI4GANILABEL_Y_FIRST, AI4GANILABEL_WIDTH_FIRST, AI4GANILABEL_HEIGHT_FIRST);
+        label->SetText(AI4GANILABEL_TEXT_FIRST);
+        label->SetFont(DEFAULT_VECTOR_FONT_FILENAME, AI4GANILABEL_FONT_FIRST);
+        label->SetStyle(STYLE_TEXT_FONT, AI4GANILABEL_FONT_FIRST);
+        label->SetAlign(TEXT_ALIGNMENT_CENTER);
+        label->SetLineBreakMode(UILabel::LINE_BREAK_OSCILLATION);
+        scrollView->Add(label);
+        /* -------------------------------------------------------------------------- */
+        AI4GImageAni = new UIImageAnimatorView();
+        if (AI4GImageAni == nullptr)
+        {
+            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AlipayBindAni::AlipayInitImageAni new AI4GImageAni fail");
+            return nullptr;
+        }
+        for (uint8_t i = 0; i < 8; i++)
+        {
+            AI4GsearchImageInfo[i].imageInfo = ImageCacheManager::GetInstance().LoadSingleRes(AI4GsearchImagePath[i]);
+            AI4GsearchImageInfo[i].imageType = IMG_SRC_IMAGE_INFO;
+            AI4GsearchImageInfo[i].pos.x = AI4GALIPAY_BIND_IMAGE_X;
+            AI4GsearchImageInfo[i].pos.y = AI4GALIPAY_BIND_IMAGE_Y;
+            AI4GsearchImageInfo[i].width = AI4GALIPAY_BIND_IMAGE_WIDTH;
+            AI4GsearchImageInfo[i].height = AI4GALIPAY_BIND_IMAGE_HEIGHT;
+        }
+        AI4GImageAni->SetPosition(AI4GALIPAY_BIND_IMAGE_X, AI4GALIPAY_BIND_IMAGE_Y, AI4GALIPAY_BIND_IMAGE_WIDTH, AI4GALIPAY_BIND_IMAGE_HEIGHT);
+        AI4GImageAni->SetImageAnimatorSrc(AI4GsearchImageInfo, 8, AI4GALIPAY_BIND_IMAGE_DELAY);
+        AI4GImageAni->SetRepeat(true);
+        AI4GImageAni->SetAutoEnable(false);
+        AI4GImageAni->SetResizeMode(UIImageView::FILL);
+        scrollView->Add(AI4GImageAni);
+        AI4GImageAni->Start();
+
+        return scrollView;
+    }
+}
index a5b9590..48c92bd 100644 (file)
@@ -23,6 +23,11 @@ namespace OHOS
     static constexpr const int16_t CHATCONTENTLABEL_TEXT_FONT = 26;
     static constexpr const int16_t CHATCONTENTLABEL_LINE_HEIGHT = 30;
 
+    static constexpr const int16_t MINDLABEL_X = 40;
+    static constexpr const int16_t MINDLABEL_Y = 25;
+    static constexpr const int16_t MINDLABEL_TEXT_FONT = 20;
+    static constexpr const int16_t MINDLABEL_LINE_HEIGHT = 26;
+
     static constexpr const int64_t RADIUS = 20;
 
     static constexpr const int16_t QUESTION_CHATCONTENTIMAGE_X = 0;
@@ -54,6 +59,7 @@ namespace OHOS
         SetUpChild();
         Add(&chatContentImage);
         chatContentScrollView.Add(&chatContentLabel);
+        chatContentScrollView.Add(&mindLabel);
         Add(&chatContentScrollView);
     }
 
@@ -61,6 +67,7 @@ namespace OHOS
     {
         Remove(&chatContentImage);
         chatContentScrollView.Remove(&chatContentLabel);
+        chatContentScrollView.Remove(&mindLabel);
         Remove(&chatContentScrollView);
     }
 
@@ -88,12 +95,24 @@ namespace OHOS
         }
         else
         {
-            if(!AiVoiceModel::GetInstance().GetIsLimitDisplayed())
+            if (!AiVoiceModel::GetInstance().GetIsLimitDisplayed())
             {
                 AiVoiceModel::GetInstance().SetIsLimitDisplayed(true);
-                chatContentLabel.SetLineBreakMode(isAiAnswerFlag ? UILabel::LINE_BREAK_ELLIPSIS : UILabel::LINE_BREAK_WRAP);//超过高度在末尾用省略号替换
+                chatContentLabel.SetLineBreakMode(isAiAnswerFlag ? UILabel::LINE_BREAK_ELLIPSIS : UILabel::LINE_BREAK_WRAP); // 超过高度在末尾用省略号替换
             }
         }
+        
+        if(isAiAnswerFlag)
+        {
+            chatContentScrollView.Resize(isAiAnswerFlag ? QUESTION_CHATCONTENTSCROLLVIEW_W : ANSWER_CHATCONTENTSCROLLVIEW_W, GetHeight());
+            mindLabel.SetY(chatContentScrollView.GetY() + chatContentScrollView.GetHeight()- 40);
+            mindLabel.SetVisible(true);
+        }
+        else
+        {
+            chatContentScrollView.Resize(isAiAnswerFlag ? QUESTION_CHATCONTENTSCROLLVIEW_W : ANSWER_CHATCONTENTSCROLLVIEW_W, GetHeight() - 30);
+            mindLabel.SetVisible(false);
+        }
     }
 
     void AivoiceChatContentListItemView::SetUpChild()
@@ -115,6 +134,17 @@ namespace OHOS
         chatContentLabel.SetLineBreakMode(UILabel::LINE_BREAK_WRAP);
         chatContentLabel.SetAlign(TEXT_ALIGNMENT_LEFT, TEXT_ALIGNMENT_CENTER);
         chatContentLabel.SetFont(DEFAULT_VECTOR_FONT_FILENAME_EN, CHATCONTENTLABEL_TEXT_FONT);
+
+        mindLabel.SetPosition(MINDLABEL_X, MINDLABEL_Y);
+        mindLabel.Resize(0, 26);
+        mindLabel.SetVisible(false);
+        mindLabel.SetText("内容由AI生成,仅供参考");
+        mindLabel.SetStyle(STYLE_TEXT_FONT, MINDLABEL_TEXT_FONT);
+        mindLabel.SetStyle(STYLE_LINE_HEIGHT, MINDLABEL_LINE_HEIGHT);
+        mindLabel.SetLineBreakMode(UILabel::LINE_BREAK_ADAPT);
+        mindLabel.SetAlign(TEXT_ALIGNMENT_LEFT, TEXT_ALIGNMENT_CENTER);
+        mindLabel.SetFont(DEFAULT_VECTOR_FONT_FILENAME_EN, MINDLABEL_TEXT_FONT);
+        mindLabel.SetTextColor(Color::GetColorFromRGBA(0x99, 0x99, 0x99, 0xff));
     }
 
 }
\ No newline at end of file
index 050d452..41e1b2b 100644 (file)
 // #include "common/image_cache_manager.h"
 namespace OHOS
 {
+    const char *listening_path_array[] = {
+        "/user/res/AIVoice/AIVoiceListening/1.bin",
+        "/user/res/AIVoice/AIVoiceListening/2.bin",
+        "/user/res/AIVoice/AIVoiceListening/3.bin",
+        "/user/res/AIVoice/AIVoiceListening/4.bin",
+        "/user/res/AIVoice/AIVoiceListening/5.bin",
+        "/user/res/AIVoice/AIVoiceListening/6.bin",
+        "/user/res/AIVoice/AIVoiceListening/7.bin",
+        "/user/res/AIVoice/AIVoiceListening/8.bin",
+        "/user/res/AIVoice/AIVoiceListening/9.bin",
+        "/user/res/AIVoice/AIVoiceListening/10.bin",
+        "/user/res/AIVoice/AIVoiceListening/11.bin",
+        "/user/res/AIVoice/AIVoiceListening/12.bin",
+        "/user/res/AIVoice/AIVoiceListening/13.bin",
+        "/user/res/AIVoice/AIVoiceListening/14.bin",
+        "/user/res/AIVoice/AIVoiceListening/15.bin",
+        "/user/res/AIVoice/AIVoiceListening/16.bin",
+        "/user/res/AIVoice/AIVoiceListening/17.bin",
+        "/user/res/AIVoice/AIVoiceListening/18.bin",
+        "/user/res/AIVoice/AIVoiceListening/19.bin",
+        "/user/res/AIVoice/AIVoiceListening/20.bin",
+        "/user/res/AIVoice/AIVoiceListening/21.bin",
+        "/user/res/AIVoice/AIVoiceListening/22.bin",
+        "/user/res/AIVoice/AIVoiceListening/23.bin",
+        "/user/res/AIVoice/AIVoiceListening/24.bin",
+        "/user/res/AIVoice/AIVoiceListening/25.bin",
+        "/user/res/AIVoice/AIVoiceListening/26.bin",
+        "/user/res/AIVoice/AIVoiceListening/27.bin",
+        "/user/res/AIVoice/AIVoiceListening/28.bin",
+        "/user/res/AIVoice/AIVoiceListening/29.bin",
+        "/user/res/AIVoice/AIVoiceListening/30.bin",
+        "/user/res/AIVoice/AIVoiceListening/31.bin",
+        "/user/res/AIVoice/AIVoiceListening/32.bin",
+        "/user/res/AIVoice/AIVoiceListening/33.bin",
+        "/user/res/AIVoice/AIVoiceListening/34.bin",
+        "/user/res/AIVoice/AIVoiceListening/35.bin",
+        "/user/res/AIVoice/AIVoiceListening/36.bin",
+        "/user/res/AIVoice/AIVoiceListening/37.bin",
+        "/user/res/AIVoice/AIVoiceListening/38.bin",
+        "/user/res/AIVoice/AIVoiceListening/39.bin",
+        "/user/res/AIVoice/AIVoiceListening/40.bin",
+    };
 
     static AivoiceListeningView *g_pAivoiceListeningView{nullptr};
 
@@ -53,8 +95,10 @@ namespace OHOS
                 AiVoiceListeningImageAnimatorView->Stop();
                 delete AiVoiceListeningImageAnimatorView;
                 AiVoiceListeningImageAnimatorView = nullptr;
-
-                FreeImageInfoArray(AiVoiceListeningPathsArray, AIVoiceListeningImagePaths, AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES);
+                for (int i = 0; i < AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES; i++)
+                {
+                    ImageCacheManager::GetInstance().UnloadSingleRes(listening_path_array[i]);
+                }
             }
 
             if (showtimeout != nullptr)
@@ -109,7 +153,7 @@ namespace OHOS
         button->SetViewId(buttonconfig.ViewId);
         button->SetStyle(STYLE_BACKGROUND_COLOR, 0xff191919);
         button->SetStyle(STYLE_BACKGROUND_OPA, 0xff);
-        button->SetStyleForState(STYLE_BACKGROUND_COLOR, 0xff383838, UIButton::PRESSED);
+        button->SetStyleForState(STYLE_BACKGROUND_COLOR, 0xff191919, UIButton::PRESSED);
 
         return button;
     }
@@ -141,7 +185,7 @@ namespace OHOS
         animatorView->SetSizeFixed(true);
         // animatorView->SetAutoEnable(false);
         // animatorView->SetResizeMode(UIImageAnimatorView::FILL);
-        animatorView->Start();
+        // animatorView->Start();
 
         return animatorView;
     }
@@ -252,33 +296,45 @@ namespace OHOS
     bool AivoiceListeningView::CreateAivoiceListeningImageAnimator(void)
     {
         WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AivoiceListeningView::CreateAivoiceListeningImageAnimator");
-        AiVoiceListeningPathsArray = CreateImageInfoArray(AIVoiceListeningImagePaths, AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES);
-        if (AiVoiceListeningPathsArray == nullptr)
+        if (AiVoiceListeningImageAnimatorView == nullptr)
         {
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AivoiceListeningView::AiVoiceListeningPathsArray  is nullptr!!");
-            return false;
+            AiVoiceListeningImageAnimatorView = new UIImageAnimatorView();
+            if (AiVoiceListeningImageAnimatorView == nullptr)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AlipayBindAni::AlipayInitImageAni new AI4GImageAni fail");
+                return false;
+            }
         }
-
-        ImageAnimatorConfig imageanimatorconfig = {
-            .x = AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_X,
-            .y = AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_Y,
-            .width = AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_W,
-            .height = AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_H,
-            .imageInfoArray = AiVoiceListeningImageInfo,
-            .pathsArray = AiVoiceListeningPathsArray,
-            .numFrames = AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES,
-            .delay = AIVOICE_LISTENING_IMAGE_ANIMATOR_DELAY,
-        };
-        AiVoiceListeningImageAnimatorView = AivoiceListeningImageAnimatorInit(imageanimatorconfig);
-        if (AiVoiceListeningImageAnimatorView == nullptr)
+        for (uint8_t i = 0; i < AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES; i++)
         {
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceListeningImageAnimatorView::AiVoiceListeningImageAnimatorView  new fail");
-            return false;
+            AiVoiceListeningImageInfo[i].imageInfo = ImageCacheManager::GetInstance().LoadSingleRes(listening_path_array[i]);
+            AiVoiceListeningImageInfo[i].imageType = IMG_SRC_IMAGE_INFO;
+            AiVoiceListeningImageInfo[i].pos.x = AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_X;
+            AiVoiceListeningImageInfo[i].pos.y = AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_Y;
+            AiVoiceListeningImageInfo[i].width = AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_W;
+            AiVoiceListeningImageInfo[i].height = AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_H;
         }
+        AiVoiceListeningImageAnimatorView->SetPosition(AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_X, AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_Y,
+                                            AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_W, AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_H);
+        AiVoiceListeningImageAnimatorView->SetImageAnimatorSrc(AiVoiceListeningImageInfo, AIVOICE_LISTENING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES, AIVOICE_LISTENING_IMAGE_ANIMATOR_DELAY);
+        AiVoiceListeningImageAnimatorView->SetRepeat(true);
+        AiVoiceListeningImageAnimatorView->SetAutoEnable(false);
+        AiVoiceListeningImageAnimatorView->SetResizeMode(UIImageView::FILL);
 
         return true;
     }
 
+    void AivoiceListeningView::StartOrStopAivoiceListeningImageAnimatorView(bool val)
+    {
+        if (AiVoiceListeningImageAnimatorView)
+        {
+            if (val)
+                AiVoiceListeningImageAnimatorView->Start();
+            else
+                AiVoiceListeningImageAnimatorView->Stop();
+        }
+    }
+
     UIScrollView *AivoiceListeningView::CreateAivoiceListeningView(void)
     {
         WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AivoiceListeningView::CreateAivoiceListeningView");
index e81a42d..be47227 100644 (file)
@@ -115,6 +115,13 @@ namespace OHOS
             scrollView = nullptr;
         }
     }
+    void AivoiceReturnResultTextView::SetRequestFocus()
+    {
+        if (chatContentList)
+        {
+            chatContentList->RequestFocus();
+        }
+    }
 
     UILabelExt *AivoiceReturnResultTextView::AivoiceReturnResultTextLabelInit(LabelConfig &labelconfig)
     {
@@ -252,8 +259,8 @@ namespace OHOS
         chatContentList->SetMaxScrollDistance(MAX_SCR_DIS);
         chatContentList->SetSwipeACCLevel(200); // 800: compensation distance
         chatContentList->SetDragACCLevel(5);    // 5: drag acceleration
-        chatContentList->SetRotateFactor(2);
-        chatContentList->RequestFocus();
+        // chatContentList->SetRotateFactor(2);
+        // chatContentList->RequestFocus();
         // chatContentList->SetIntercept(true);
         chatContentList->SetAdapter(chatContentListAdapter);
         chatContentList->RefreshList();
index 6e7db53..30984de 100644 (file)
 namespace OHOS
 {
 
+    const char *thinking_path_array[] = {
+        "/user/res/AIVoice/AIVoiceThinking/1.bin",
+        "/user/res/AIVoice/AIVoiceThinking/2.bin",
+        "/user/res/AIVoice/AIVoiceThinking/3.bin",
+        "/user/res/AIVoice/AIVoiceThinking/4.bin",
+        "/user/res/AIVoice/AIVoiceThinking/5.bin",
+        "/user/res/AIVoice/AIVoiceThinking/6.bin",
+        "/user/res/AIVoice/AIVoiceThinking/7.bin",
+        "/user/res/AIVoice/AIVoiceThinking/8.bin",
+        "/user/res/AIVoice/AIVoiceThinking/9.bin",
+        "/user/res/AIVoice/AIVoiceThinking/10.bin",
+        "/user/res/AIVoice/AIVoiceThinking/11.bin",
+        "/user/res/AIVoice/AIVoiceThinking/12.bin",
+        "/user/res/AIVoice/AIVoiceThinking/13.bin",
+        "/user/res/AIVoice/AIVoiceThinking/14.bin",
+        "/user/res/AIVoice/AIVoiceThinking/15.bin",
+        "/user/res/AIVoice/AIVoiceThinking/16.bin",
+        "/user/res/AIVoice/AIVoiceThinking/17.bin",
+        "/user/res/AIVoice/AIVoiceThinking/18.bin",
+        "/user/res/AIVoice/AIVoiceThinking/19.bin",
+        "/user/res/AIVoice/AIVoiceThinking/20.bin",
+        "/user/res/AIVoice/AIVoiceThinking/21.bin",
+        "/user/res/AIVoice/AIVoiceThinking/22.bin",
+        "/user/res/AIVoice/AIVoiceThinking/23.bin",
+        "/user/res/AIVoice/AIVoiceThinking/24.bin",
+        "/user/res/AIVoice/AIVoiceThinking/25.bin",
+        "/user/res/AIVoice/AIVoiceThinking/26.bin",
+        "/user/res/AIVoice/AIVoiceThinking/27.bin",
+        "/user/res/AIVoice/AIVoiceThinking/28.bin",
+        "/user/res/AIVoice/AIVoiceThinking/29.bin",
+        "/user/res/AIVoice/AIVoiceThinking/30.bin",
+        "/user/res/AIVoice/AIVoiceThinking/31.bin",
+        "/user/res/AIVoice/AIVoiceThinking/32.bin",
+        "/user/res/AIVoice/AIVoiceThinking/33.bin",
+        "/user/res/AIVoice/AIVoiceThinking/34.bin",
+        "/user/res/AIVoice/AIVoiceThinking/35.bin",
+        "/user/res/AIVoice/AIVoiceThinking/36.bin",
+        "/user/res/AIVoice/AIVoiceThinking/37.bin",
+        "/user/res/AIVoice/AIVoiceThinking/38.bin",
+        "/user/res/AIVoice/AIVoiceThinking/39.bin",
+        "/user/res/AIVoice/AIVoiceThinking/40.bin",
+    };
+
     static AivoiceThinkingView *g_pAivoiceThinkingView{nullptr};
 
     AivoiceThinkingView::AivoiceThinkingView()
@@ -54,8 +97,11 @@ namespace OHOS
                 delete AiVoiceThinkingImageAnimatorView;
                 AiVoiceThinkingImageAnimatorView = nullptr;
 
-                // FreeImagePathsArray(AiVoiceThinkingPathsArray, AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES);
-                FreeImageInfoArray(AiVoiceThinkingPathsArray, AIVoiceThinkingImagePaths, AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES);
+                for (int i = 0; i < AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES; i++)
+                {
+                    ImageCacheManager::GetInstance().UnloadSingleRes(thinking_path_array[i]);
+                }
+
             }
 
             if (cancelThink != nullptr)
@@ -104,7 +150,7 @@ namespace OHOS
         button->SetViewId(buttonconfig.ViewId);
         button->SetStyle(STYLE_BACKGROUND_COLOR, 0xff191919);
         button->SetStyle(STYLE_BACKGROUND_OPA, 0xff);
-        button->SetStyleForState(STYLE_BACKGROUND_COLOR, 0xff383838, UIButton::PRESSED);
+        button->SetStyleForState(STYLE_BACKGROUND_COLOR, 0xff191919, UIButton::PRESSED);
 
         return button;
     }
@@ -136,7 +182,7 @@ namespace OHOS
         animatorView->SetSizeFixed(true);
         // animatorView->SetAutoEnable(false);
         // animatorView->SetResizeMode(UIImageAnimatorView::FILL);
-        animatorView->Start();
+        // animatorView->Start();
 
         return animatorView;
     }
@@ -235,52 +281,48 @@ namespace OHOS
     bool AivoiceThinkingView::CreateAivoiceThinkingImageAnimator(void)
     {
         WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "AivoiceThinkingView::CreateAivoiceThinkingImageAnimator");
-        AiVoiceThinkingPathsArray = CreateImageInfoArray(AIVoiceThinkingImagePaths, AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES);
-        if (AiVoiceThinkingPathsArray == nullptr)
+        if (AiVoiceThinkingImageAnimatorView == nullptr)
         {
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AivoiceThinkingView::AiVoiceThinkingPathsArray  is nullptr!!");
-            return false;
+            AiVoiceThinkingImageAnimatorView = new UIImageAnimatorView();
+            if (AiVoiceThinkingImageAnimatorView == nullptr)
+            {
+                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AivoiceThinkingView::AivoiceThinkingImageAnimatorView  new fail");
+                return false;
+            }
         }
-
-        ImageAnimatorConfig imageanimatorconfig = {
-            .x = AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_X,
-            .y = AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_Y,
-            .width = AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_W,
-            .height = AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_H,
-            .imageInfoArray = AiVoiceThinkingImageInfo,
-            .pathsArray = AiVoiceThinkingPathsArray,
-            .numFrames = AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES,
-            .delay = AIVOICE_THINKING_IMAGE_ANIMATOR_DELAY,
-        };
-        AiVoiceThinkingImageAnimatorView = AivoiceThinkingImageAnimatorInit(imageanimatorconfig);
-        if (AiVoiceThinkingImageAnimatorView == nullptr)
+        for (uint8_t i = 0; i < AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES; i++)
         {
-            WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AiVoiceThinkingImageAnimatorView::AiVoiceThinkingImageAnimatorView  new fail");
-            return false;
+            AiVoiceThinkingImageInfo[i].imageInfo = ImageCacheManager::GetInstance().LoadSingleRes(thinking_path_array[i]);
+            AiVoiceThinkingImageInfo[i].imageType = IMG_SRC_IMAGE_INFO;
+            AiVoiceThinkingImageInfo[i].pos.x = AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_X;
+            AiVoiceThinkingImageInfo[i].pos.y = AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_Y;
+            AiVoiceThinkingImageInfo[i].width = AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_W;
+            AiVoiceThinkingImageInfo[i].height = AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_H;
         }
+        AiVoiceThinkingImageAnimatorView->SetPosition(AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_X, AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_Y,
+                                                      AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_W, AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_H);
+        AiVoiceThinkingImageAnimatorView->SetImageAnimatorSrc(AiVoiceThinkingImageInfo, AIVOICE_THINKING_IMAGE_ANIMATOR_VIEW_NUM_FRAMES, AIVOICE_THINKING_IMAGE_ANIMATOR_DELAY);
+        AiVoiceThinkingImageAnimatorView->SetRepeat(true);
+        AiVoiceThinkingImageAnimatorView->SetAutoEnable(false);
+        AiVoiceThinkingImageAnimatorView->SetResizeMode(UIImageView::FILL);
 
         return true;
     }
 
-    UIScrollView *AivoiceThinkingView::CreateAivoiceThinkingView(void)
+    void AivoiceThinkingView::StartOrStopAiVoiceThinkingImageAnimatorView(bool val)
     {
-        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AivoiceThinkingView::CreateAivoiceThinkingView");
-#if 0
-        if (scrollView == nullptr)
+        if (AiVoiceThinkingImageAnimatorView != nullptr)
         {
-            if (!CreateAivoiceThinkingScrollView() || !CreateAivoiceThinkingLabel() ||
-                !CreateAivoiceThinkingButton() || !CreateAivoiceThinkingImageAnimator())
-            {
-                WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AivoiceThinkingView::CreateAivoiceThinkingView fail!!");
-                return nullptr;
-            }
-            
-            scrollView->Add(title);
-            scrollView->Add(AiVoiceThinkingImageAnimatorView);
-            scrollView->Add(cancelThinkButton);
-            scrollView->Add(cancelThink);
+            if (val)
+                AiVoiceThinkingImageAnimatorView->Start();
+            else
+                AiVoiceThinkingImageAnimatorView->Stop();
         }
-#endif
+    }
+
+    UIScrollView *AivoiceThinkingView::CreateAivoiceThinkingView(void)
+    {
+        WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AivoiceThinkingView::CreateAivoiceThinkingView");
         if (!CreateAivoiceThinkingScrollView())
         {
             WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "AivoiceThinkingView::CreateAivoiceThinkingScrollView fail!!");
index 877e5a3..b45ef69 100644 (file)
@@ -1,5 +1,8 @@
 #ifndef __CAT1_WS_H__
 #define __CAT1_WS_H__
+
+#include "bk_websocket.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
@@ -22,6 +25,8 @@ void uapi_UI_stop_start_asr_timeout(void);
 
 bool uapi_get_server_state_is_end(void);
 
+void ai_cleanup_resources(void);
+
 typedef enum
 {
     AI_TYPE_0=0,