# /*
#  * Copyright (C) 2020, KylinSoft Co., Ltd.
#  *
#  * This program is free software: you can redistribute it and/or modify
#  * it under the terms of the GNU General Public License as published by
#  * the Free Software Foundation, either version 3 of the License, or
#  * (at your option) any later version.
#  *
#  * This program is distributed in the hope that it will be useful,
#  * but WITHOUT ANY WARRANTY; without even the implied warranty of
#  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  * GNU General Public License for more details.
#  *
#  * You should have received a copy of the GNU General Public License
#  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
#  */

#!/usr/bin/python3
import os
import json
import dbus
import dbus.service
import logging
import subprocess
from SystemUpdater.modules.i18n import _
from .Core.loop import mainloop
from SystemUpdater.Core.DbusControl import DbusControl
from SystemUpdater.packageManager.pmUtils import *
from SystemUpdater.packageManager.pmWorker import *
from SystemUpdater.modules.rate_limiter import UPDATE_RATE_CONFIG,P2P_RATE_CONFIG,get_download_limit

UPDATER_DBUS_INTERFACE = 'com.kylin.UpgradeStrategies.interface'
UPDATER_DBUS_PATH = '/com/kylin/UpgradeStrategies'
UPDATER_DBUS_SERVICE = 'com.kylin.UpgradeStrategies'
RUN_UNATTENDED_UPGRADE = '/var/run/unattended-upgrades.pid'

#颜色设置
COLORLOG_SUFFIX = "\033[0m"

# Define some foreground colors
BLACK = 30
RED = 31
GREEN = 32
YELLOW = 33
BLUE = 34
MAGENTA = 35
CYAN = 36
WHITE = 37

#字体颜色
FRONT_COLOR_SEQ = "\033[1;%dm"
#背景颜色
BACK_COLOR_SEQ = "\033[%d;1m"

COLORLOG_PREFIX     = FRONT_COLOR_SEQ % GREEN                                                                 
COLORMETHOR_PREFIX  = FRONT_COLOR_SEQ % CYAN

UU_UPGRADE_MODE_AUTOMATIC_DOWNLOAD = 0
UU_UPGRADE_MODE_MANUAL = 1
UU_UPGRADE_MODE_AUTOMATIC_INSTALL = 2
UU_UPGRADE_MODE_BEFORE_SHUTDOWN = 3


#dbus 建立
class UpgradeStrategiesDbusController(dbus.service.Object):
    """ this is a helper to provide the UpdateManagerIFace """

    ACTION_DEFUALT_STATUS   =-1
    ACTION_UPDATE           = 0
    ACTION_DOWNLOADONLY     = 1
    ACTION_DEPLOY           = 2
    ACTION_ROLLBACK         = 3

    RETURN_BUSY_STATE       = 1
    RETURN_BUSY_DESC        = "In the process of updating or Upgrading..."

    P2P_DEDAULT_PATH        = "/etc/default/apt-p2p"
    RETURN_SUCCESS_CODE     = 0
    RETURN_SUCCESS_DESC     = ""

    RETURN_UNKNOWN_CODE     =-1
    RETURN_UNKNOWN_DESC     = ""

    def __init__(self, parent, bus_name,
                object_path=UPDATER_DBUS_PATH):
        dbus.service.Object.__init__(self, bus_name, object_path)
        self.parent         = parent
        self.bus            = dbus.SystemBus()

        self.now_working    = self.ACTION_DEFUALT_STATUS

        self.prohibit_list  = []
        if not self.parent.options.debug:
            self.prohibit_list = ["dbus-send","gdbus"]
        
        self.dbus_control = DbusControl(self.bus)
    
    def _check_prohibit_user(self, sender_name):
        if sender_name in self.prohibit_list:
            raise dbus.exceptions.DBusException("ERROR: You are not allowed to perform this action.")

    def __check_change__(self, _config = None, _section = "", _option = "", _value = ""):
        if _config == None:
            return False
        if _value == _config.getWithDefault(_section,_option,_value," "):
            return True
        return False

    @dbus.service.method(UPDATER_DBUS_INTERFACE,
                        in_signature="", out_signature="",
                        sender_keyword="caller_name")
    def Quit(self, caller_name=""):
        """Request a shutdown of the daemon."""
        try:
            sender_name = self.dbus_control.check_sender(caller_name)
            #如果在下载就请求 取消
            logging.info("UpgradeStrategies service quitting...")
            mainloop.quit()
            logging.debug("Exit")
        except Exception as e:
            logging.error(str(e))
            return self.RETURN_UNKNOWN_CODE,str(e)

    ## dbus接口: 开启或关闭预下载功能
    @dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='s', out_signature='is',sender_keyword='sender')
    def ChangingP2PStatus(self,_status,sender = None):
        status = str(_status)
        sender_name = self.dbus_control.check_sender(sender)
        logging.info(COLORMETHOR_PREFIX+'method'+COLORLOG_SUFFIX+' ChangingP2PStatus, _status = %s , sender name: %s',status,sender_name)
        
        if os.path.exists(self.P2P_DEDAULT_PATH):
            if status == "enable":
                with open(self.P2P_DEDAULT_PATH, 'w+') as configfile:
                    configfile.write("#enable=true\n")
                #第一次进行检查是否已经开启
                args = ["systemctl","is-enabled","apt-p2p.service"]
                p = subprocess.run(args, stdout=subprocess.PIPE,stderr=subprocess.STDOUT,text=True)
                if p.returncode != 0:
                    logging.info("Apt-p2p service is not runing and will be enable...")
                    #第二次进行重启
                    args = ["systemctl","enable","apt-p2p.service"]
                    p = subprocess.run(args, stdout=subprocess.PIPE,stderr=subprocess.STDOUT,text=True)
                    if p.returncode == 0:
                        logging.info("Service Enable Execute successfully")
                        #第三次进行重启
                        args = ["systemctl","restart","apt-p2p.service"]
                        p = subprocess.run(args, stdout=subprocess.PIPE,stderr=subprocess.STDOUT,text=True)
                        if p.returncode == 0:
                            logging.info("Restart Execute successfully")
                            return self.RETURN_SUCCESS_CODE,self.RETURN_SUCCESS_DESC
                        else:
                            logging.error(str(p.stdout))
                            logging.error("Failed to execute reboot")
                            return self.RETURN_UNKNOWN_CODE,str(p.stdout)
                    else:
                        logging.error(str(p.stdout))
                        logging.error("Failed to execute enable")
                        return self.RETURN_UNKNOWN_CODE,str(p.stdout)
                else:
                    logging.info("Apt-p2p service has been enabled and not need to reabled...")
                    return self.RETURN_SUCCESS_CODE,self.RETURN_SUCCESS_DESC

            elif status == "disable":
                with open(self.P2P_DEDAULT_PATH, 'w+') as configfile:
                    configfile.write("enable=false\n")

                args = ["systemctl","is-enabled","apt-p2p.service"]
                p = subprocess.run(args, stdout=subprocess.PIPE,stderr=subprocess.STDOUT,text=True)
                if p.returncode == 0:
                    logging.info("Apt-p2p service is runing and will be disable...")
                    args = ["systemctl","disable","apt-p2p.service"]
                    p = subprocess.run(args, stdout=subprocess.PIPE,stderr=subprocess.STDOUT,text=True)
                    if p.returncode == 0:
                        logging.info("Service disable Execute successfully")

                        args = ["systemctl","stop","apt-p2p.service"]
                        p = subprocess.run(args, stdout=subprocess.PIPE,stderr=subprocess.STDOUT,text=True)

                        if p.returncode == 0:
                            logging.info("Stop Execute successfully")
                            return self.RETURN_SUCCESS_CODE,self.RETURN_SUCCESS_DESC
                        else:
                            logging.error(str(p.stdout))
                            logging.error("Failed to execute Stop")
                            return self.RETURN_UNKNOWN_CODE,str(p.stdout)
                    else:
                        logging.error(str(p.stdout))
                        logging.error("Failed to execute disable")
                        return self.RETURN_UNKNOWN_CODE,str(p.stdout)
                else:
                    logging.info("Apt-p2p service has been disabled and not need to redisabled...")
                    return self.RETURN_SUCCESS_CODE,self.RETURN_SUCCESS_DESC
            else:
                logging.warning("error: input value _status=%s",status)
        else:
            logging.warning("apt-p2p function is not install...")

    @dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='b', out_signature='b',sender_keyword='sender')
    def SetUpgradeStrategyState(self,state,sender=None):
        state=bool(state)
        sender_name = self.dbus_control.check_sender(sender)
        logging.info(COLORMETHOR_PREFIX+'method'+COLORLOG_SUFFIX+' SetUpdateStrategyState, upgrade strategy state is %r, sender name: %s .',state,sender_name)
        try:
            if state:
                if not self.__check_change__(self.parent.uuconfigs, "updateStrategiesManager", "strategiesState", "True"):
                    self.parent.uuconfigs.setValue("updateStrategiesManager", "strategiesState", "True", True)                    
                    self.StrategyChanged("strategiesState","True")            
            else:
                if not self.__check_change__(self.parent.uuconfigs, "updateStrategiesManager", "strategiesState", "False"):
                    self.parent.uuconfigs.setValue("updateStrategiesManager", "strategiesState", "False", True)
                    self.StrategyChanged("strategiesState","False")
        except Exception as e:
            logging.error(str(e))
            return False
        return True
    
        ## 设置更新周期
    @dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='s', out_signature='b',sender_keyword='sender')
    def SetUpgradeMode(self, mode, sender = None):
        _mode = str(mode)
        sender_name = self.dbus_control.check_sender(sender)
        logging.info(COLORMETHOR_PREFIX+'method'+COLORLOG_SUFFIX+' SetUpgradeMode, mode: %s , sender:%s .',_mode,sender_name)                        
        try:
            if not self.__check_change__(self.parent.uuconfigs, "updateStrategiesManager", "installType", _mode):
                self.parent.uuconfigs.setValue("updateStrategiesManager", "installType", _mode, True)
                self.StrategyChanged("installType",_mode)
        except Exception as e:
            logging.error(str(e))
            return False
        return True
    
    ## dbus接口: 开启或关闭预下载功能
    @dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='bs', out_signature='b',sender_keyword='sender')
    def SetPreDownloadState(self, _state, _time, sender = None):
        state = bool(_state)
        time  = str(_time)
        sender_name = self.dbus_control.check_sender(sender)
        logging.info(COLORMETHOR_PREFIX+'method'+COLORLOG_SUFFIX+' SetPreDownloadState, state is %r, time: %s, sender name: %s .',state,time,sender_name)
        try:
            if state:
                if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "preDownload", "on"):
                    self.parent.uuconfigs.setValue("autoUpgradePolicy", "preDownload", "on", True)
                    self.PropertyChanged("preDownload","on")
                if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "preDownloadTime", time):
                    self.parent.uuconfigs.setValue("autoUpgradePolicy", "preDownloadTime", time, True)
                    self.PropertyChanged("preDownloadTime",time)
            else:
                if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "preDownload", "off"):
                    self.parent.uuconfigs.setValue("autoUpgradePolicy", "preDownload", "off", True)
                    self.PropertyChanged("preDownload","off")
        except Exception as e:
            logging.error(str(e))
            return False
        return True

    ## 设置更新周期
    @dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='i', out_signature='b',sender_keyword='sender')
    def SetUpdateDays(self, days, sender = None):
        _days = int(days)
        sender_name = self.dbus_control.check_sender(sender)
        logging.info(COLORMETHOR_PREFIX+'method'+COLORLOG_SUFFIX+' SetUpdateDays, days: %d , sender:%s .'\
                        ,_days,sender_name)
        try:
            if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "updateDays", _days):
                self.parent.uuconfigs.setValue("autoUpgradePolicy", "updateDays", str(_days), True)
                self.PropertyChanged("updateDays",str(_days))
        except Exception as e:
            logging.error(str(e))
            return False
        return True
    
    # 设置自动更新时间
    @dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='s', out_signature='bs',sender_keyword='sender')
    def SetAutoUpgradeRandomRange(self,randomRange,sender=None):
        _randomRange = str(randomRange)
        sender_name = self.dbus_control.check_sender(sender)
        logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' SetAutoUpgradeRandomRange will be set value %s, sender: %s .',\
                            _randomRange,sender_name)
        try:
            if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "randomRange", _randomRange):
                self.parent.uuconfigs.setValue("autoUpgradePolicy", "randomRange", _randomRange, True)
                self.PropertyChanged("randomRange",_randomRange)
        except Exception as e:
            logging.error(str(e))
        return True,"success"

    ## 设置是否开启自动重启,以及设置自动重启的时间
    @dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='bs', out_signature='b',sender_keyword='sender')
    def SetAutomaticReboot(self, status, reboot_time, sender = None):
        _state = bool(status)
        _reboot_time  = str(reboot_time)
        sender_name = self.dbus_control.check_sender(sender)
        logging.info(COLORMETHOR_PREFIX+'method'+COLORLOG_SUFFIX+' SetAutomaticReboot, status is %r, reboot_time: %s, sender name: %s .'\
                        ,_state,_reboot_time,sender_name)
        try:
            if _state:
                if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "automaticReboot", "on"):
                    self.parent.uuconfigs.setValue("autoUpgradePolicy", "automaticReboot", "on", True)
                    self.PropertyChanged("automaticReboot","on")
                if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "automaticRebootTime", _reboot_time):
                    self.parent.uuconfigs.setValue("autoUpgradePolicy", "automaticRebootTime", _reboot_time, True)
                    self.PropertyChanged("automaticRebootTime",_reboot_time)
            else:
                if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "automaticReboot", "off"):
                    self.parent.uuconfigs.setValue("autoUpgradePolicy", "automaticReboot", "off", True)
                    self.PropertyChanged("automaticReboot","off")
        except Exception as e:
            logging.error(str(e))
            return False
        return True

    ## dbus接口: 开启关闭自动更新功能
    @dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='b', out_signature='b', sender_keyword='sender')
    def SetAutoUpgradeState(self, _state, sender):
        state = bool(_state)
        sender_name = self.dbus_control.check_sender(sender)
        logging.info(COLORMETHOR_PREFIX+'method'+COLORLOG_SUFFIX+' SetAutoUpgradeState, state is %r ...',state)
        try:
            if state:
                if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "autoUpgradeState", "on"):
                    self.parent.uuconfigs.setValue("autoUpgradePolicy", "autoUpgradeState", "on", True)
                    self.parent.sqlite3_server.insert_into_display("autoupdate_allow", "true")
                    self.PropertyChanged("autoUpgradeState","on")
                self.ButtonStatusChange("autoUpgradeStatus", "true")
            else :
                if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "autoUpgradeState", "off"):
                    self.parent.uuconfigs.setValue("autoUpgradePolicy", "autoUpgradeState", "off", True)
                    self.parent.sqlite3_server.insert_into_display("autoupdate_allow", "false")
                    self.PropertyChanged("autoUpgradeState","off")
                self.ButtonStatusChange("autoUpgradeStatus", "false")
        except Exception as e:
            logging.error(str(e))
            return False
        return True

    ## dbus接口: 设置自动更新策略
    @dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='is', out_signature='b', sender_keyword='sender')
    def SetAutoUpgradeMode(self, mode, time, sender):
        _time = str(time)
        sender_name = self.dbus_control.check_sender(sender)
        logging.info(COLORMETHOR_PREFIX+'method'+COLORLOG_SUFFIX+' SetAutoUpgradeMode, mode is %s, time is %s ...',mode,_time)
        try:
            if mode == UU_UPGRADE_MODE_AUTOMATIC_DOWNLOAD:
                if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "downloadMode", "timing"):
                    self.parent.uuconfigs.setValue("autoUpgradePolicy", "downloadMode", "timing", True)
                    self.PropertyChanged("downloadMode","timing")
                if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "downloadTime", str(_time)):
                    self.parent.uuconfigs.setValue("autoUpgradePolicy", "downloadTime", str(_time), True)
                    self.PropertyChanged("downloadTime",str(_time))
                self.ButtonStatusChange("autoUpgradeTime", str(_time))
            elif mode == UU_UPGRADE_MODE_AUTOMATIC_INSTALL:
                if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "installMode", "timing"):
                    self.parent.uuconfigs.setValue("autoUpgradePolicy", "installMode", "timing", True)
                    self.PropertyChanged("installMode","timing")
                if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "installTime", str(_time)):
                    self.parent.uuconfigs.setValue("autoUpgradePolicy", "installTime", str(_time), True)
                    self.PropertyChanged("installTime",str(_time))
            elif mode == UU_UPGRADE_MODE_BEFORE_SHUTDOWN:
                if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "installTime", "bshutdown"):
                    self.parent.uuconfigs.setValue("autoUpgradePolicy", "installMode", "bshutdown", True)
                    self.PropertyChanged("installMode","bshutdown")
            elif mode == UU_UPGRADE_MODE_MANUAL:
                if not self.__check_change__(self.parent.uuconfigs, "autoUpgradePolicy", "downloadMode", "manual"):
                    self.parent.uuconfigs.setValue("autoUpgradePolicy", "downloadMode", "manual", True)
                    self.PropertyChanged("downloadMode","manual")
        except Exception as e:
            logging.error(str(e))
            return False
        return True


    # 限速相关配置接口
    # 设置下载限速
    @dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='sb', out_signature='is',sender_keyword='sender')
    def SetDownloadspeedMax(self, download_limit_value, download_limit, sender = None):
        sender_name = self.dbus_control.check_sender(sender)
        logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' SetDownloadspeedMax, download_limit_value:%s, download_limit:%r, sender name: %s .'%(download_limit_value, download_limit, sender_name))

        rate_config = {
            "policy_limits": False,
            "rate_limits": [],
            "default_download": "0",
            "global_download_limit": "0"
        }

        try:
            with open(UPDATE_RATE_CONFIG, 'r') as f:
                current_config = json.load(f)
        except Exception as e:
            logging.error("%s",e)
            current_config = rate_config

        if download_limit:
            download_limit_value = str(download_limit_value).strip()
            if not download_limit_value.isdigit():
                return self.RETURN_UNKNOWN_CODE,""
            current_config["global_download_limit"] = download_limit_value
        else:
            current_config["global_download_limit"] = "0"

        with open(UPDATE_RATE_CONFIG, 'w') as config_file:
            json.dump(current_config, config_file, indent=4)

        return self.RETURN_SUCCESS_CODE,self.RETURN_SUCCESS_DESC

    @dbus.service.method(UPDATER_DBUS_INTERFACE,in_signature='s',out_signature='is',sender_keyword='sender')
    def SetUpgradeStrategyJson(self,input_json,sender=None):
        def check_diff_status(diff: dict) -> bool:
            """校验字典差异状态

            参数:
                diff: 包含added/modified字段的字典

            返回:
                bool: 存在非空字段返回True，否则False
                异常时自动返回False
            """
            try:
                # 类型安全校验
                if not isinstance(diff, dict):
                    return False

                # 字段存在性检查
                added = diff.get("added", {})  # 默认空字典
                modified = diff.get("modified", {})

                # 深度判空逻辑
                return bool(added) or bool(modified)
            except Exception as e:  # 兜底异常处理
                return False
        def json_string_to_dict(json_str):
            """
            将 JSON 字符串转换为字典，转换失败时返回空字典
            
            参数:
                json_str (str): 需要转换的 JSON 格式字符串
                
            返回:
                dict: 转换成功的字典对象，或空字典（转换失败时）
            """
            try:
                # 尝试解析 JSON 字符串
                data = json.loads(json_str)
                
                # 确保解析结果是字典类型
                if isinstance(data, dict):
                    return data
                else:
                    # 当解析结果是列表等非字典类型时，也视为异常
                    return {}
                    
            except (json.JSONDecodeError, TypeError) as e:
                # 捕获 JSON 解析错误和类型错误
                return {}
            except Exception as e:
                # 捕获其他未知异常
                return {}
        sender_name = self.dbus_control.check_sender(sender)
        try:
            logging.info(COLORMETHOR_PREFIX+'Method '+COLORLOG_SUFFIX+'SetUpgradeStrategyJson sender:%s'%sender_name)
            logging.info(input_json)
            data = json_string_to_dict(input_json)
            diff_result=self.parent.strategy_json_config.update_and_diff(data)

            if(check_diff_status(diff_result)):
                self.parent.strategy_json_config.save_to_file(file_path="/var/lib/unattended-upgrades/kylin-update-strategy.json",indent=4)
                diff_str=json.dumps(diff_result)
                self.UpgradeStrategyChanged(diff_str)
                return self.RETURN_SUCCESS_CODE,diff_str
            else:
                return self.RETURN_UNKNOWN_CODE,"no diffrence"
        except Exception as e:
            logging.error(e)
            return self.RETURN_UNKNOWN_CODE,str(e)
     
    @dbus.service.method(UPDATER_DBUS_INTERFACE,in_signature='a{sv}',out_signature='is',sender_keyword='sender')
    def SetUpgradeStrategy(self,input_json,sender=None):
        def check_diff_status(diff: dict) -> bool:
            """校验字典差异状态

            参数:
                diff: 包含added/modified字段的字典

            返回:
                bool: 存在非空字段返回True，否则False
                异常时自动返回False
            """
            try:
                # 类型安全校验
                if not isinstance(diff, dict):
                    return False

                # 字段存在性检查
                added = diff.get("added", {})  # 默认空字典
                modified = diff.get("modified", {})

                # 深度判空逻辑
                return bool(added) or bool(modified)
            except Exception as e:  # 兜底异常处理
                return False
        def convert_a_sv_to_json(a_sv_data):
            """
            将DBus的a{sv}类型数据转换为JSON对象

            Args:
                a_sv_data (dbus.Dictionary): D-Bus类型的a{sv}数据（字典格式）

            Returns:
                str: JSON格式字符串
            """
            def _parse_variant(value):
                # 递归解析变体类型中的嵌套数据
                if isinstance(value, dbus.Dictionary):
                    return {k: _parse_variant(v) for k, v in value.items()}
                elif isinstance(value, dbus.Array):
                    return [_parse_variant(v) for v in value]
                elif isinstance(value, dbus.Struct):
                    return tuple(_parse_variant(v) for v in value)
                elif isinstance(value, (dbus.String, dbus.ObjectPath)):
                    return str(value)
                elif isinstance(value, dbus.Boolean):
                    return bool(value)
                elif isinstance(value, (dbus.Int16, dbus.Int32, dbus.Int64)):
                    return int(value)
                elif isinstance(value, (dbus.Double, dbus.UInt16, dbus.UInt32, dbus.UInt64)):
                    return float(value) if '.' in str(value) else int(value)
                else:
                    return value

            # 转换主逻辑
            json_dict = {}
            for key, variant in a_sv_data.items():
                json_dict[key] = _parse_variant(variant)

            return json.dumps(json_dict, indent=2)
        sender_name = self.dbus_control.check_sender(sender)
        try:
            logging.info(COLORMETHOR_PREFIX+'Method '+COLORLOG_SUFFIX+'SetUpgradeStrategy sender:%s'%sender_name)
            logging.info(input_json)
            data = json.loads(convert_a_sv_to_json(input_json))
            diff_result=self.parent.strategy_json_config.update_and_diff(data)

            if(check_diff_status(diff_result)):
                self.parent.strategy_json_config.save_to_file(file_path="/var/lib/unattended-upgrades/kylin-update-strategy.json",indent=4)
                diff_str=json.dumps(diff_result)
                self.UpgradeStrategyChanged(diff_str)
                return self.RETURN_SUCCESS_CODE,diff_str
            else:
                return self.RETURN_UNKNOWN_CODE,"no diffrence"
        except Exception as e:
            logging.error(e)
            return self.RETURN_UNKNOWN_CODE,str(e)
    
    @dbus.service.method(UPDATER_DBUS_INTERFACE,out_signature='s',sender_keyword='sender')
    def GetUpgradeStrategyJson(self,sender=None):
        sender_name = self.dbus_control.check_sender(sender)
        try:
            logging.info(COLORMETHOR_PREFIX+'Method '+COLORLOG_SUFFIX+'GetUpgradeStrategyJson sender:%s',sender_name)
            data=self.parent.strategy_json_config.get_json_object()
            return json.dumps(data)
        except Exception as e:
            logging.error(str(e))
            return '{}'

    @dbus.service.method(UPDATER_DBUS_INTERFACE,out_signature='a{sv}',sender_keyword='sender')
    def GetUpgradeStrategy(self,sender=None):
        from dbus.types import Int32, Int64, String, Boolean, Double, Array,Dictionary
        def json_to_asv(data):
           """
           将 JSON 字典转换为 D-Bus a{sv} 类型
           参数：
               data: dict - 输入字典（需确保键为字符串）
           返回：
               dbus.Dictionary - 符合 a{sv} 签名的 D-Bus 字典
           异常：
               ValueError - 输入类型错误或数据格式不合法
               TypeError - 存在不支持的类型
           """
           def _convert_value(value):
               # 递归处理嵌套结构
               if isinstance(value, dict):
                   return Dictionary(
                       {k: _convert_value(v) for k, v in value.items()},
                       signature=dbus.Signature('sv'),
                       variant_level=1  # 隐式创建变体层[3](@ref)
                   )
               elif isinstance(value, list):
                   return Array(
                       [_convert_value(v) for v in value],
                       signature=dbus.Signature('v'),
                       variant_level=1
                   )
               elif isinstance(value, bool):
                   return Boolean(value)
               elif isinstance(value, int):
                   return Int64(value) if abs(value) > 0x7FFFFFFF else Int32(value)
               elif isinstance(value, float):
                   return Double(value)
               elif isinstance(value, str):
                   return String(value)
               else:
                   raise TypeError(f"不支持的类型: {type(value)}")

           try:
               # 输入类型验证
               if not isinstance(data, dict):
                   raise ValueError("输入必须是字典类型")

               # 键类型验证（需全部为字符串）
               if not all(isinstance(k, str) for k in data.keys()):
                   raise ValueError("字典键必须是字符串")

               return Dictionary(
                   {k: _convert_value(v) for k, v in data.items()},
                   signature=dbus.Signature('sv'),
                   variant_level=1
               )
           except (TypeError, ValueError) as e:
               raise e
           except Exception as e:
               raise RuntimeError(f"未知错误: {str(e)}") from e
        sender_name = self.dbus_control.check_sender(sender)
        try:
            logging.info(COLORMETHOR_PREFIX+'Method '+COLORLOG_SUFFIX+'GetUpgradeStrategy sender:%s',sender_name)
            data=self.parent.strategy_json_config.get_json_object()
            return json_to_asv(data)
        except Exception as e:
            logging.error(str(e))
            return {}
 
    @dbus.service.method(UPDATER_DBUS_INTERFACE,out_signature='is',sender_keyword='sender')
    def InitUpgradeStrategy(self,sender=None):
        sender_name = self.dbus_control.check_sender(sender)
        try:
            logging.info(COLORMETHOR_PREFIX+'Method '+COLORLOG_SUFFIX+'InitUpgradeStrategy sender:%s',sender_name)
            self.parent.strategy_json_config.reload_config()
            return self.RETURN_SUCCESS_CODE,""      
        except Exception as e:
            logging.error(str(e))
            return self.RETURN_UNKNOWN_CODE,str(e)
    
    #配置自动更新策略json字符串
    @dbus.service.method(UPDATER_DBUS_INTERFACE,in_signature='a{sv}',out_signature='is',sender_keyword='sender')
    def SetUpgradeScheme(self,input_json,sender=None):
        from collections.abc import Mapping
        import re
        def is_valid_json_data(input_data: Mapping) -> bool:
            """
            验证输入数据是否符合JSON标准规范
            参数:
                input_data (Mapping): 需要验证的字典类型数据
            返回:
                bool: 是否为合法的JSON可序列化数据
            功能特性:
                1. 类型层级验证
                2. 深度递归检查
                3. 异常安全处理
            """
            def _recursive_check(obj):
                # 基础类型检查
                if isinstance(obj, (str, int, float, bool, type(None))):
                    return True
                # 容器类型检查
                if isinstance(obj, Mapping):
                    return all(
                        isinstance(k, str) and _recursive_check(v) 
                        for k, v in obj.items()
                    )
                if isinstance(obj, (list, tuple)):
                    return all(_recursive_check(e) for e in obj)
                return False
            try:
                # 第一阶段：类型结构验证
                if not isinstance(input_data, Mapping):
                    return False
                # 第二阶段：递归深度验证
                if not _recursive_check(input_data):
                    return False
                # 第三阶段：实际序列化验证
                json.dumps(
                    input_data,
                    ensure_ascii=False,
                    check_circular=True,  # 检测循环引用
                    separators=(',', ':'),
                    allow_nan=False       # 禁止非数字值
                )
                return True
            except (TypeError, ValueError, OverflowError):  # 捕获所有序列化异常
                return False
            except Exception:  # 兜底异常处理
                return False
        def generate_time_output(input_data: dict) -> dict:
            """
            处理时间字段并生成指定格式的字典输出
            
            参数：
            input_data - 包含download_time和install_time的原始数据
            
            返回：
            动态生成的字典，仅包含有效数据项
            
            规则：
            1. 当download_time列表非空时，生成downloadtime字段（键名转换）
            2. 当install_time列表非空时，提取第一个元素的start_time生成installtime字段
            3. 空列表或不存在字段时自动过滤
            """
            output = {}
            
            # 处理download_time（键名转换逻辑）
            download_periods = [
                {"start": item["start_time"], "end": item["end_time"]}
                for item in input_data.get("download_time", [])
                if isinstance(item, dict) and "start_time" in item and "end_time" in item
            ]
            if download_periods:  # 仅当列表非空时生成字段
                output["downloadtime"] = download_periods
            
            # 处理install_time（首项提取逻辑）
            install_items = input_data.get("install_time", [])
            if install_items and isinstance(install_items[0], dict):  # 检查列表非空且首项有效
                first_install = install_items[0]
                if "start_time" in first_install:
                    output["installtime"] = first_install["start_time"]
            
            return output 
        def convert_a_sv_to_json(a_sv_data):
            """
            将DBus的a{sv}类型数据转换为JSON对象

            Args:
                a_sv_data (dbus.Dictionary): D-Bus类型的a{sv}数据（字典格式）

            Returns:
                str: JSON格式字符串
            """
            def _parse_variant(value):
                # 递归解析变体类型中的嵌套数据
                if isinstance(value, dbus.Dictionary):
                    return {k: _parse_variant(v) for k, v in value.items()}
                elif isinstance(value, dbus.Array):
                    return [_parse_variant(v) for v in value]
                elif isinstance(value, dbus.Struct):
                    return tuple(_parse_variant(v) for v in value)
                elif isinstance(value, (dbus.String, dbus.ObjectPath)):
                    return str(value)
                elif isinstance(value, dbus.Boolean):
                    return bool(value)
                elif isinstance(value, (dbus.Int16, dbus.Int32, dbus.Int64)):
                    return int(value)
                elif isinstance(value, (dbus.Double, dbus.UInt16, dbus.UInt32, dbus.UInt64)):
                    return float(value) if '.' in str(value) else int(value)
                else:
                    return value

            # 转换主逻辑
            json_dict = {}
            for key, variant in a_sv_data.items():
                json_dict[key] = _parse_variant(variant)

            return json.dumps(json_dict, indent=2)
        sender_name = self.dbus_control.check_sender(sender)
        try:
            logging.info(COLORMETHOR_PREFIX+'Method '+COLORLOG_SUFFIX+'SetUpgradeScheme sender:%s',sender_name)
            if (is_valid_json_data(input_json)):
                configjsonstr=convert_a_sv_to_json(input_json)
                logging.info(configjsonstr)
                json_data=json.loads(configjsonstr)
                data={}
                if(json_data.get('auto_download','true')=='true'):
                    data.update({'updatemode':'autoupdate'})
                    autoupdate=generate_time_output(json_data)
                    period=int(json_data.get('download_period',{}).get('day',1))
                    mode=json_data.get('mode','shutdown')
                    autoupdate.update({"mode":mode}) 
                    autoupdate.update({"period":period})
                    data.update({"autoupdate":autoupdate})
                elif(json_data.get('auto_download','false')=='false'):
                    data.update({'updatemode':'off'})
                return self.SetUpgradeStrategy(data)
            else:
                return self.RETURN_UNKNOWN_CODE,'invalid json format'        
        except Exception as e:
            logging.error(str(e))
            return self.RETURN_UNKNOWN_CODE,str(e)

    # 获取下载限速
    @dbus.service.method(UPDATER_DBUS_INTERFACE, out_signature='bs',sender_keyword='sender')
    def GetDownloadspeedLimitValue(self,sender = None):
        sender_name = self.dbus_control.check_sender(sender)
        logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' GetDownloadspeedLimitValue sender: %s .', sender_name)

        download_limit          = False
        download_limit_value    = "0"
        try:
            download_rate = get_download_limit()
            logging.info("GetDownloadspeedLimitValue download_rate: %s.", download_rate)

            download_limit = True if download_rate != "0" else False
            download_limit_value = download_rate
        except Exception as e:
            logging.error("GetDownloadspeedLimitValue error:%s", e)
        
        return download_limit, str(download_limit_value)

    # 设置系统分时限速策略
    @dbus.service.method(UPDATER_DBUS_INTERFACE,in_signature='a{sv}',out_signature='is',sender_keyword='sender')
    def SetUpdateTimedDownloadRate(self,_downloadRate,sender=None):
        sender_name = self.dbus_control.check_sender(sender)
        logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' SetUpdateTimedDownloadRate sender:%s, current policy:%s', sender_name, _downloadRate)

        try:
            with open(UPDATE_RATE_CONFIG, 'r') as f:
                current_config = json.load(f)
                
            for key in _downloadRate:
                current_config[key] =  _downloadRate[key]
        except Exception as e:
            logging.error(e)
            # 如果文件损坏或不是合法 JSON，则用默认
            current_config = _downloadRate
        # 转换格式，防止写入的是0或者1，而是true或者false这种格式
        current_config["policy_limits"] = bool(current_config["policy_limits"])
        try:
            with open(UPDATE_RATE_CONFIG, 'w') as config_file:
                json.dump(current_config, config_file, indent=4)
        except Exception as e:
            logging.error(str(e))
            return self.RETURN_UNKNOWN_CODE,"Rate limits error"

        return self.RETURN_SUCCESS_CODE,""
    
    # 设置P2P下载限速策略
    @dbus.service.method(UPDATER_DBUS_INTERFACE,in_signature='a{sv}',out_signature='is',sender_keyword='sender')
    def SetP2PTimedDownloadRate(self,_downloadRate,sender=None):
        sender_name = self.dbus_control.check_sender(sender)
        logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' SetP2PTimedDownloadRate sender:%s, current policy:%s', sender_name, _downloadRate)
        try:
            with open(P2P_RATE_CONFIG, 'w') as config_file:
                json.dump(_downloadRate, config_file, indent=4)
        except Exception as e:
            logging.error(str(e))
            return self.RETURN_UNKNOWN_CODE,"Rate limits error"

        return self.RETURN_SUCCESS_CODE,""


    # 是否允许关机前更新
    @dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='ss', out_signature='bs', sender_keyword='sender')
    def UnattendedUpgradeValue(self, operation, value="false", sender=None):
        sender_name = self.dbus_control.check_sender(sender)
        logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' UnattendedUpgradeValue sender:%s ', sender_name)
        if operation.lower() != "get" and operation.lower() != "set":
            return False, 'Please input [\"set\", \"value\"] to set. \nor [\"get\"] to get whether updates are allowed before shutdown.'
        if operation == "set":
            try:
                logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' UnattendedUpgradeValue is going to %s [allow_unattended_upgrades_shutdown] value to %s.'%(operation,value))
                self.parent.sqlite3_server.insert_into_display("allow_unattended_upgrades_shutdown", value.lower())
            except Exception as e:
                logging.error(str(e))
                return False,str(e)
        else:
            logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' UnattendedUpgradeValue is going to %s [allow_unattended_upgrades_shutdown] value.'%(operation))
            try:
                value = self.parent.sqlite3_server.select_from_display("allow_unattended_upgrades_shutdown")
                logging.info("[allow_unattended_upgrades_shutdown] value is %s."%(value))
            except Exception as e:
                logging.error(str(e))
                return False,str(e)
        return True,"success"

    # 获取数据库值
    @dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='bss', out_signature='s', sender_keyword='sender')
    def GetSetDatabaseInfo(self, gs, table, field, sender):
        Text = 'NULL'
        sender_name = self.dbus_control.check_sender(sender)
        try:
            if gs: #get 
                if table == 'display':
                    Text = self.parent.sqlite3_server.select_from_display(str(field))
                    logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' GetDatabaseInfo Table:%s Field:%s Text:%s',table,field,Text)
            else: #set 
                if table == 'display' and "=" in field:
                    field, value = str(field).split("=")
                    logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' SetDatabaseInfo Table:%s Field:%s', table, field)
                    self.parent.sqlite3_server.insert_into_display(field, value)
                    return "success"
        except Exception as e:
            logging.error(str(e))
            return Text
        return Text

    ## dbus接口: 发送立即更新的信号
    @dbus.service.method(UPDATER_DBUS_INTERFACE, out_signature='b', sender_keyword='sender')
    def AutoUpgradeAllNow(self, sender):
        sender_name = self.dbus_control.check_sender(sender)
        logging.info(COLORMETHOR_PREFIX+'method'+COLORLOG_SUFFIX+' AutoUpgradeAllNow ...')
        try:
            self.UpgradeAllNow()
        except Exception as e:
            logging.error(str(e))
            return False
        return True

    #设置数据库配置信息
    @dbus.service.method(UPDATER_DBUS_INTERFACE,in_signature='ss',out_signature='b',sender_keyword='sender')
    def DatabaseInfoSet(self,field_name,field_value,sender=None):
        Status = False
        sender_name = self.dbus_control.check_sender(sender)
        logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' SetDatabaseInfo,field_name:%s,field_value:%s,caller:%s .',\
                field_name,field_value,sender_name)
        Status = self.parent.sqlite3_server.insert_into_display(field_name,field_value)
        return bool(Status)

    #数据库获取配置信息
    @dbus.service.method(UPDATER_DBUS_INTERFACE,in_signature='s',out_signature='s',sender_keyword='sender')
    def DatabaseInfoGet(self,field_name,sender=None):
        field_value = ''
        sender_name = self.dbus_control.check_sender(sender)
        logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' GetDatabaseInfo field_name:%s caller:%s',field_name,sender_name)
        field_value = self.parent.sqlite3_server.select_from_display(str(field_name))
        logging.info("Get field_value:%s",field_value)
        return field_value

    #  =============================== 包安装卸载 =============================== */
    @dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='ssbbs', out_signature='is', sender_keyword='sender')
    def InstallDebFile(self,source = "unKnown", path = "", _check_local_dep = False, _auto_satisfy = False, user_lang = '', sender=None):
        try:
            sender_name = self.dbus_control.check_sender(sender)

            check_local_dep     = bool(_check_local_dep)
            auto_satisfy        = bool(_auto_satisfy)
            deb_path            = str(path)

            logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' InstallDebFile and check_local_dep:%r, auto_satisfy:%r, current_lang:%s , InstallDebFile sender: %s .',\
                                        check_local_dep, auto_satisfy, user_lang, sender_name)

            if not hasattr(self.parent, 'pmworker') or self.parent.pmworker is None:
                self.parent.pmworker = PmWorker(self.parent)

            if self.parent.pmworker.trans_is_runing.value:
                logging.warning('Updater In the process of Upgrading, ignore \'%s\' InstallDebFile(%s) request ...', \
                                sender_name, path)
                return self.RETURN_BUSY_STATE, self.RETURN_BUSY_DESC

            self.parent.pmworker.start_deb_install(deb_path, _check_local_dep, _auto_satisfy, source, sender)
            return self.RETURN_SUCCESS_CODE, self.RETURN_SUCCESS_DESC
        except Exception as e:
            logging.error("InstallDebFile error:%s", str(e))
            return self.RETURN_UNKNOWN_CODE,str(e)

    @dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='as', out_signature='is', sender_keyword='sender')
    def InstallPackages(self, pkg_list = [], sender=None):
        try:
            sender_name = self.dbus_control.check_sender(sender)

            logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' InstallPackages: %s .',\
                                                                        ",".join(pkg_list))

            if not hasattr(self.parent, 'pmworker') or self.parent.pmworker is None:
                self.parent.pmworker = PmWorker(self.parent)

            if self.parent.pmworker.trans_is_runing.value:
                logging.warning('Updater In the process of Upgrading, ignore \'%s\' InstallPackages(%s) request ...', \
                                sender_name, ",".join(pkg_list))
                return self.RETURN_BUSY_STATE, self.RETURN_BUSY_DESC

            self.parent.pmworker.start_back_upgrade(pkg_list, sender)

            return self.RETURN_SUCCESS_CODE, self.RETURN_SUCCESS_DESC
        except Exception as e:
            logging.error(str(e))
            return self.RETURN_UNKNOWN_CODE, str(e)

    @dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='sss', out_signature='is', sender_keyword='sender')
    def PackageTagInstallOnline(self, _name, _type, _compat, sender=None):
        try:
            sender_name = self.dbus_control.check_sender(sender)

            logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' PackageTagInstallOnline: %s, %s, %s .',\
                        _name, _type, _compat)

            if not hasattr(self.parent, 'pmworker') or self.parent.pmworker is None:
                self.parent.pmworker = PmWorker(self.parent)

            if self.parent.pmworker.trans_is_runing.value:
                logging.warning('Updater In the process of Upgrading, ignore \'%s\' PackageTagInstallOnline(%s) request ...', \
                                sender_name, _name)
                return self.RETURN_BUSY_STATE, self.RETURN_BUSY_DESC

            self.parent.pmworker.start_tag_online_install(_name, _type, _compat, sender)

            return self.RETURN_SUCCESS_CODE, self.RETURN_SUCCESS_DESC
        except Exception as e:
            logging.error(str(e))
            return self.RETURN_UNKNOWN_CODE, str(e)

    @dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='sss', out_signature='is', sender_keyword='sender')
    def PackageTagInstallOffline(self, _name, _type, _compat, sender=None):
        try:
            sender_name = self.dbus_control.check_sender(sender)

            logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' PackageTagInstallOnline: %s, %s, %s .',\
                        _name, _type, _compat)

            if not hasattr(self.parent, 'pmworker') or self.parent.pmworker is None:
                self.parent.pmworker = PmWorker(self.parent)

            if self.parent.pmworker.trans_is_runing.value:
                logging.warning('Updater In the process of Upgrading, ignore \'%s\' PackageTagInstallOffline(%s) request ...', \
                                sender_name, _name)
                return self.RETURN_BUSY_STATE, self.RETURN_BUSY_DESC

            self.parent.pmworker.start_tag_offline_install(_name, _type, _compat, sender)

            return self.RETURN_SUCCESS_CODE, self.RETURN_SUCCESS_DESC
        except Exception as e:
            logging.error(str(e))
            return self.RETURN_UNKNOWN_CODE, str(e)

    @dbus.service.method(UPDATER_DBUS_INTERFACE, in_signature='asss', out_signature='is', sender_keyword='sender')
    def PurgePackages(self, _purge_list, cur_user, user_lang = '', sender=None):
        try:
            sender_name = self.dbus_control.check_sender(sender)
            purge_list = [str(pkg) for pkg in _purge_list]

            logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' PurgePackages Sender:%s and purge list is:%s...',sender_name, purge_list)

            if not hasattr(self.parent, 'pmworker') or self.parent.pmworker is None:
                self.parent.pmworker = PmWorker(self.parent)

            if self.parent.pmworker.trans_is_runing.value:
                logging.warning('Updater In the process of Upgrading, ignore \'%s\' PurgePackages(%s) request ...', \
                                sender_name, ",".join(_purge_list))
                return self.RETURN_BUSY_STATE, self.RETURN_BUSY_DESC

            self.parent.pmworker.start_purge_pkgs(purge_list, sender)
            return self.RETURN_SUCCESS_CODE, self.RETURN_SUCCESS_DESC
        except Exception as e:
            logging.error(str(e))
            return self.RETURN_UNKNOWN_CODE,str(e)

    @dbus.service.method(UPDATER_DBUS_INTERFACE,in_signature='ss',out_signature='i',sender_keyword='sender')
    def PackageInstallStatus(self, name, version, sender=None):
        try:
            sender_name = self.dbus_control.check_sender(sender)
            logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' PackageInstallStatus, name:%s, version:%s, sender:%s .',
                        name, version, sender_name)

            if not hasattr(self.parent, 'pmworker') or self.parent.pmworker is None:
                self.parent.pmworker = PmWorker(self.parent)

            return self.parent.pmworker.check_package_status(name, version, sender)
        except Exception as e:
            logging.error("PackageInstallStatus err:%s", e)
            # return -100
            return self.RETURN_UNKNOWN_CODE,str(e)

    @dbus.service.method(UPDATER_DBUS_INTERFACE,in_signature='s',out_signature='s',sender_keyword='sender')
    def PackageInstallVersion(self, _name, sender=None):
        package_version = ""
        try:
            sender_name = self.dbus_control.check_sender(sender)
            logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' PackageInstallStatus, _name:%s, sender:%s .',
                        _name, sender_name)

            if not hasattr(self.parent, 'pmworker') or self.parent.pmworker is None:
                self.parent.pmworker = PmWorker(self.parent)

            package_version = self.parent.pmworker.get_package_version(_name, sender)

        except Exception as e:
            logging.error("PackageInstallVersion err:%s", e)

        return package_version

    @dbus.service.method(UPDATER_DBUS_INTERFACE,in_signature='ss',out_signature='b',sender_keyword='sender')
    def PackageIsOnlineInstallable(self, _name, _version, sender=None):
        _is_online_installable = False
        try:
            sender_name = self.dbus_control.check_sender(sender)
            logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' PackageIsOnlineInstallable, _name:%s, _version:%s, sender:%s .',
                        _name, _version, sender_name)

            if not hasattr(self.parent, 'pmworker') or self.parent.pmworker is None:
                self.parent.pmworker = PmWorker(self.parent)

            _is_online_installable = self.parent.pmworker.is_package_online_installable(_name, _version, sender)

        except Exception as e:
            logging.error("PackageIsOnlineInstallable err:%s", e)

        return _is_online_installable

    @dbus.service.method(UPDATER_DBUS_INTERFACE,out_signature='b',sender_keyword='sender')
    def GetAutocheckStatus(self,sender=None):
        sender_name = self.dbus_control.check_sender(sender)
        logging.info(COLORMETHOR_PREFIX+'Method'+COLORLOG_SUFFIX+' GetAutocheckStatus sender: %s .', sender_name)

        autocheckStatus = True

        try:
            autocheckStatus = self.parent.sqlite3_server.select_from_display("auto_check")
            logging.info("[auto_check] value is %s.", autocheckStatus)
            autocheckStatus = True if autocheckStatus.lower() == "true" else False
        except Exception as e:
            logging.error("GetAutocheckStatus: %s.", str(e))

        return autocheckStatus

    #卸载完成的信号
    @dbus.service.signal(UPDATER_DBUS_INTERFACE,signature='bss')
    def PurgePackagesFinished(self, success,error_string='',error_desc=''):
        logging.info(COLORLOG_PREFIX + "Emitting"+ COLORLOG_SUFFIX + " PurgePackagesFinished success = %r , error_string = %s , error_desc = %s ",\
                    success,error_string,error_desc)

    #卸载进度信息 0~100 进度信息 101为非预期的信号
    @dbus.service.signal(UPDATER_DBUS_INTERFACE,signature='iss')
    def PurgePkgStatusChanged(self,progress,status,current_details):
        logging.info(COLORLOG_PREFIX + "Emitting" + COLORLOG_SUFFIX +" PurgePkgStatusChanged progress = %d , status = %s ,current_details = %s",\
            progress,status,current_details)
    
    #卸载完成的信号，包含当前正在卸载的包名
    @dbus.service.signal(UPDATER_DBUS_INTERFACE,signature='bsss')
    def PurgePackagesFinishedWithPkgname(self, success,error_string='',error_desc='',current_pkg=''):
        logging.info(COLORLOG_PREFIX + "Emitting"+ COLORLOG_SUFFIX + " PurgePackagesFinishedWithPkgname success = %r , error_string = %s , error_desc = %s , current purge package = %s" ,\
                    success,error_string,error_desc,current_pkg)
    
    #卸载完成的信号
    @dbus.service.signal(UPDATER_DBUS_INTERFACE,signature='bssss')
    def PurgePackagesFinishedWithErrCode(self, success,error_string='',error_desc='',current_pkg='',error_code=''):
        logging.info(COLORLOG_PREFIX + "Emitting"+ COLORLOG_SUFFIX + " PurgePackagesFinishedWithErrCode success = %r , error_string = %s , error_desc = %s , current purge package = %s , error_code = %s",\
                    success,error_string,error_desc,current_pkg,error_code)

    #卸载进度信息 0~100 进度信息 101为非预期的信号，包含当前正在卸载的包名
    @dbus.service.signal(UPDATER_DBUS_INTERFACE,signature='isss')
    def PurgePkgStatusChangedWithPkgname(self,progress,status,current_details,current_pkg=''):
        logging.info(COLORLOG_PREFIX + "Emitting" + COLORLOG_SUFFIX +" PurgePkgStatusChangedWithPkgname progress = %d , status = %s ,current_details = %s, current purge package = %s",\
            progress,status,current_details,current_pkg)

    #安装deb包完成的信号
    @dbus.service.signal(UPDATER_DBUS_INTERFACE,signature='bss')
    def InstalldebFinished(self, success,error_string='',error_desc=''):
        logging.info(COLORLOG_PREFIX + "Emitting"+ COLORLOG_SUFFIX + " InstalldebFinished success = %r , error_string = %s , error_desc = %s ",\
                    success,error_string,error_desc)

    #安装deb包完成的信号
    @dbus.service.signal(UPDATER_DBUS_INTERFACE,signature='bsss')
    def InstalldebFinishedWithErrCode(self, success,error_string='',error_desc='',error_code=''):
        logging.info(COLORLOG_PREFIX + "Emitting"+ COLORLOG_SUFFIX + " InstalldebFinishedWithErrCode success = %r , error_string = %s , error_desc = %s , error_code = %s",\
                    success,error_string,error_desc,error_code)

    @dbus.service.signal(UPDATER_DBUS_INTERFACE,signature='bssss')
    def InstalldebFinishedWithPkgname(self, success,error_string='',error_desc='',error_code='',current_pkg=''):
        logging.info(COLORLOG_PREFIX + "Emitting"+ COLORLOG_SUFFIX + " InstalldebFinishedWithPkgname success = %r , error_string = %s , error_desc = %s , error_code = %s, current_pkg = %s",\
                    success,error_string,error_desc,error_code,current_pkg)

    #安装进度信息 0~100 进度信息 101为非预期的信号
    @dbus.service.signal(UPDATER_DBUS_INTERFACE,signature='iss')
    def InstalldebStatusChanged(self,progress,status,current_details):
        logging.info(COLORLOG_PREFIX + "Emitting" + COLORLOG_SUFFIX +" InstalldebStatusChanged progress = %d , status = %s ,current_details = %s",\
            progress,status,current_details)

    @dbus.service.signal(UPDATER_DBUS_INTERFACE,signature='is')
    def EnvBuildStatusChanged(self, progress, status):
        logging.info(COLORLOG_PREFIX + "Emitting" + COLORLOG_SUFFIX +" EnvBuildStatusChanged progress = %d , status = %s",\
            progress,status)

    @dbus.service.signal(UPDATER_DBUS_INTERFACE,signature='bs')
    def EnvBuildStatusFinished(self, progress, status):
        logging.info(COLORLOG_PREFIX + "Emitting" + COLORLOG_SUFFIX +" EnvBuildStatusFinished progress = %d , status = %s",\
            progress,status)

    #限速修改信号
    @dbus.service.signal(UPDATER_DBUS_INTERFACE,signature='ss')
    def ButtonStatusChange(self, signal_types = '', value=''):
        logging.info(COLORLOG_PREFIX + "Emitting"+ COLORLOG_SUFFIX + " ButtonStatusChange signal_types = %s, value = %s.",signal_types, value)

    # dbus 信号：用于发送立即更新信号
    @dbus.service.signal(UPDATER_DBUS_INTERFACE)
    def UpgradeAllNow(self):
        logging.info(COLORLOG_PREFIX + "Emitting" + COLORLOG_SUFFIX +" UpgradeAllNow") 
    
    # dbus 信号：用于发送自动更新配置更改信号
    @dbus.service.signal(UPDATER_DBUS_INTERFACE)
    def ChangeUpgradePolicy(self):
        logging.info(COLORLOG_PREFIX + "Emitting" + COLORLOG_SUFFIX +" ChangeUpgradePolicy") 


    #限速修改信号
    @dbus.service.signal(UPDATER_DBUS_INTERFACE,signature='ss')
    def ButtonStatusChange(self, signal_types = '', value=''):
        logging.info(COLORLOG_PREFIX + "Emitting"+ COLORLOG_SUFFIX + " ButtonStatusChange signal_types = %s, value = %s.",signal_types, value)

    @dbus.service.signal(UPDATER_DBUS_INTERFACE,signature='basss')
    def UpdateInstallFinished(self, success, upgrade_group, error_string='', error_desc=''):
        logging.info(COLORLOG_PREFIX + "Emitting" + COLORLOG_SUFFIX +" UpdateInstallFinished success = %r , upgrade_group = %a, error_string = %s , error_desc = %s ",\
                     success, upgrade_group, error_string, error_desc)

    # signal：属性发生改变
    @dbus.service.signal(dbus_interface=UPDATER_DBUS_INTERFACE,
                         signature="ss")
    def PropertyChanged(self, property, value):
        logging.info(COLORLOG_PREFIX + "Emitting" + COLORLOG_SUFFIX +" PropertyChanged: ( %s, %s )" % (property, value))

    # signal：属性发生改变
    @dbus.service.signal(dbus_interface=UPDATER_DBUS_INTERFACE,
                         signature="ss")
    def StrategyChanged(self, property, value):
        logging.info(COLORLOG_PREFIX + "Emitting" + COLORLOG_SUFFIX +" StrategyChanged: ( %s, %s )" % (property, value))

    #更新策略改变
    @dbus.service.signal(UPDATER_DBUS_INTERFACE, signature='s')
    def UpgradeStrategyChanged(self, diff):
        logging.info(COLORLOG_PREFIX + "Emitting" + COLORLOG_SUFFIX +" UpgradeStrategyChanged: %s"%diff)
