From 273abb544a51b15c6bb2640215e57fa14485b9fa Mon Sep 17 00:00:00 2001 From: xionglinlin Date: Wed, 3 Jun 2026 17:49:20 +0800 Subject: [PATCH] feat: add post-upgrade check for Wayland in treeland environment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Add `isWayland` and `postUpdateCheckCompleted` properties to UpdateModel with QML bindings 2. Implement `doCheckSystemOnWayland` in UpdateWorker to perform staged system check (CSS_BeforeLogin → CSS_AfterLogin) after upgrade completion 3. Update desktop autostart entry to skip dde-update process under Wayland, preventing restart issues 4. Modify QML UI to show busy state during post-update check and bypass backup dialog for Wayland 5. This solves the issue where dde-update fails to start after system restart in treeland environment, ensuring system integrity via staged verification Log: Added post-upgrade system check feature for Wayland to ensure proper system functionality after updates Influence: 1. Test upgrade on X11 environment to verify no regression (postUpdateCheckCompleted remains true) 2. Test upgrade on treeland/Wayland environment to verify staged check runs correctly 3. Verify busy indicator shows during check and hides after completion 4. Test upgrade failure scenario to ensure check completes even on error 5. Verify dde-update autostart is disabled under Wayland 6. Test multiple consecutive upgrades to ensure check state resets properly feat: 为 Wayland 环境(treeland)添加更新后系统检查功能 1. 为 UpdateModel 添加 isWayland 和 postUpdateCheckCompleted 属性及 QML 绑定 2. 在 UpdateWorker 中实现 doCheckSystemOnWayland 方法,在更新完成后分阶 段执行系统检查(CSS_BeforeLogin → CSS_AfterLogin) 3. 更新桌面自动启动条目,在 Wayland 环境下跳过 dde-update 进程,避免重启 问题 4. 修改 QML UI 在更新后检查期间显示繁忙状态,并在 Wayland 下跳过备份对 话框 5. 解决 treeland 环境下系统重启后 dde-update 无法启动的问题,通过分阶段 验证确保系统完整性 Log: 新增 Wayland 环境下的更新后系统检查功能,确保系统正常运行 Influence: 1. 测试 X11 环境下的升级功能,确认无回归(postUpdateCheckCompleted 保持 为 true) 2. 测试 treeland/Wayland 环境下的升级功能,确认分阶段检查正确执行 3. 验证检查期间显示繁忙指示器,完成后隐藏 4. 测试升级失败场景,确保即使出错检查也能完成 5. 验证 Wayland 下 dde-update 自动启动被禁用 6. 测试多次连续升级,确保检查状态正确重置 PMS: BUG-347525 BUG-347529 Change-Id: I832f7c7c55dd13158d13f0c3d25478030a39999c --- .../operation/updatemodel.cpp | 11 +++ src/dcc-update-plugin/operation/updatemodel.h | 6 ++ .../operation/updatework.cpp | 81 +++++++++++++++++++ src/dcc-update-plugin/operation/updatework.h | 7 ++ src/dcc-update-plugin/qml/UpdateMain.qml | 9 ++- .../misc/dde-update-autostart.desktop | 2 +- 6 files changed, 113 insertions(+), 3 deletions(-) diff --git a/src/dcc-update-plugin/operation/updatemodel.cpp b/src/dcc-update-plugin/operation/updatemodel.cpp index 1e68d221a..98c1cf767 100644 --- a/src/dcc-update-plugin/operation/updatemodel.cpp +++ b/src/dcc-update-plugin/operation/updatemodel.cpp @@ -46,6 +46,7 @@ UpdateModel::UpdateModel(QObject* parent) , m_updateDisabledIcon("") , m_updateDisabledTips("") , m_batterIsOK(false) + , m_postUpdateCheckCompleted(true) // 非 Wayland 默认为 true,Wayland 下检查完成后再置为 true , m_lastStatus(Default) , m_showCheckUpdate(false) , m_checkUpdateIcon("") @@ -222,6 +223,16 @@ void UpdateModel::setBatterIsOK(bool ok) Q_EMIT batterIsOKChanged(ok); } +void UpdateModel::setPostUpdateCheckCompleted(bool completed) +{ + if (m_postUpdateCheckCompleted == completed) { + return; + } + + m_postUpdateCheckCompleted = completed; + Q_EMIT postUpdateCheckCompletedChanged(completed); +} + void UpdateModel::setForceUpdateText(const QString& updateTime, int lastoreStatus) { if (!updateTime.isEmpty()) { diff --git a/src/dcc-update-plugin/operation/updatemodel.h b/src/dcc-update-plugin/operation/updatemodel.h index 7d1bb6a89..efb7b3696 100644 --- a/src/dcc-update-plugin/operation/updatemodel.h +++ b/src/dcc-update-plugin/operation/updatemodel.h @@ -100,6 +100,7 @@ class UpdateModel : public QObject Q_PROPERTY(bool upgradeDeliveryEnable READ upgradeDeliveryEnable NOTIFY upgradeDeliveryEnableChanged FINAL) Q_PROPERTY(bool p2pUpdateEnabled READ isP2PUpdateEnabled NOTIFY p2pUpdateEnableStateChanged FINAL) Q_PROPERTY(bool forceUpdate READ forceUpdate NOTIFY forceUpdateChanged FINAL) + Q_PROPERTY(bool postUpdateCheckCompleted READ postUpdateCheckCompleted NOTIFY postUpdateCheckCompletedChanged FINAL) Q_PROPERTY(UpdateHistoryModel *historyModel READ historyModel NOTIFY historyModelChanged FINAL) @@ -261,6 +262,9 @@ class UpdateModel : public QObject bool isPrivateUpdate() const { return m_isPrivateUpdate; } void setIsPrivateUpdate(bool isPrivateUpdate); + bool postUpdateCheckCompleted() const { return m_postUpdateCheckCompleted; } + void setPostUpdateCheckCompleted(bool completed); + UpdatesStatus updateStatus(ControlPanelType type) const; UpdatesStatus updateStatus(UpdateType type) const; QList updateTypesList(ControlPanelType type) const; @@ -419,6 +423,7 @@ public slots: void updateInfoChanged(UpdateType); void isUpdatableChanged(const bool isUpdatablePackages); void isPrivateUpdateChanged(const bool isPrivateUpdate); + void postUpdateCheckCompletedChanged(bool completed); void updateStatusChanged(ControlPanelType, UpdatesStatus); void controlTypeChanged(); void lastErrorChanged(UpdatesStatus, UpdateErrorType); @@ -457,6 +462,7 @@ public slots: QString m_updateDisabledIcon; QString m_updateDisabledTips; bool m_batterIsOK; + bool m_postUpdateCheckCompleted; int m_lastStatus; bool m_immutableAutoRecovery; diff --git a/src/dcc-update-plugin/operation/updatework.cpp b/src/dcc-update-plugin/operation/updatework.cpp index 9de67a434..17f732dd1 100644 --- a/src/dcc-update-plugin/operation/updatework.cpp +++ b/src/dcc-update-plugin/operation/updatework.cpp @@ -132,6 +132,9 @@ UpdateWorker::UpdateWorker(UpdateModel* model, QObject* parent) , m_backupJob(nullptr) , m_installPackageJob(nullptr) , m_removePackageJob(nullptr) + , m_checkSystemJob(nullptr) + , m_updateMode(0) + , m_currentCheckStage(0) { qCDebug(logDccUpdatePlugin) << "Initializing UpdateWorker"; qRegisterMetaType("UpdatesStatus"); @@ -151,6 +154,7 @@ UpdateWorker::~UpdateWorker() deleteJob(m_backupJob); deleteJob(m_installPackageJob); deleteJob(m_removePackageJob); + deleteJob(m_checkSystemJob); if (m_lastoreHeartBeatTimer != nullptr) { if (m_lastoreHeartBeatTimer->isActive()) { @@ -774,6 +778,11 @@ void UpdateWorker::doUpgrade(int updateTypes, bool doBackup) cleanLaStoreJob(m_distUpgradeJob); cleanLaStoreJob(m_backupJob); + if (DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsWaylandPlatform)) { + m_updateMode = updateTypes; + m_model->setPostUpdateCheckCompleted(false); + } + QDBusPendingCall call = m_updateInter->DistUpgradePartly(updateTypes, doBackup); QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher(call, this); connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, updateTypes, watcher, doBackup] { @@ -1711,6 +1720,13 @@ void UpdateWorker::onDistUpgradeStatusChanged(const QString& status) if (updateStatus == UpgradeComplete) { cleanLaStoreJob(m_distUpgradeJob); updateSystemVersion(); + + // TODO: treeland 环境下重启后无法启动 dde-update 进程, 这里直接在安装更新完成后,进行检查: + // 串行执行: CheckUpgrade(stage=1, CSS_BeforeLogin) → CheckUpgrade(stage=2, CSS_AfterLogin) → 标记完成 + if (DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsWaylandPlatform)) { + doCheckSystemOnWayland(1); + } + } else { if (updateStatus == UpgradeFailed && m_distUpgradeJob) { const QString& description = m_distUpgradeJob->description(); @@ -1858,3 +1874,68 @@ void UpdateWorker::cleanUpgradeDeliveryCache() } }); } + +void UpdateWorker::doCheckSystemOnWayland(int stage) +{ + qCInfo(logDccUpdatePlugin) << "treeland: start check system, stage:" << stage; + m_currentCheckStage = stage; + + QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(m_updateInter->CheckUpgrade(m_updateMode, stage), this); + connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, watcher] { + QDBusPendingReply reply = *watcher; + if (reply.isError()) { + qCWarning(logDccUpdatePlugin) << "CheckUpgrade stage" << m_currentCheckStage + << "failed:" << reply.error().message(); + // 即使检查失败也标记完成,不阻塞后续流程 + m_model->setPostUpdateCheckCompleted(true); + } else { + const QString jobPath = reply.value().path(); + qCInfo(logDccUpdatePlugin) << "Check system job created:" << jobPath << "stage:" << m_currentCheckStage; + setCheckSystemJob(jobPath); + } + watcher->deleteLater(); + }); +} + +void UpdateWorker::setCheckSystemJob(const QString& jobPath) +{ + qCInfo(logDccUpdatePlugin) << "Create check system job, path:" << jobPath; + if (m_checkSystemJob || jobPath.isEmpty()) { + qCWarning(logDccUpdatePlugin) << "Check system job already exists or path is empty"; + m_model->setPostUpdateCheckCompleted(true); + return; + } + + m_checkSystemJob = new UpdateJobDBusProxy(jobPath, this); + connect(m_checkSystemJob, &UpdateJobDBusProxy::StatusChanged, this, &UpdateWorker::onCheckSystemJobStatusChanged); + // 主动触发一次状态同步,避免 job 在连接信号前已完成 + onCheckSystemJobStatusChanged(m_checkSystemJob->status()); +} + +void UpdateWorker::onCheckSystemJobStatusChanged(const QString& status) +{ + qCInfo(logDccUpdatePlugin) << "Check system job status changed, stage:" << m_currentCheckStage << "status:" << status; + + // 仅关注终态:failed / succeed / end + if (status == "failed" || status == "succeed" || status == "end") { + cleanLaStoreJob(m_checkSystemJob); + + if (m_currentCheckStage == 1) { + if (status == "failed") { + qCWarning(logDccUpdatePlugin) << "CheckUpgrade stage CSS_BeforeLogin failed, cannot continue to CSS_AfterLogin"; + m_model->setPostUpdateCheckCompleted(true); + return; + } else if (status == "end") { + // CSS_BeforeLogin 阶段完成,继续 CSS_AfterLogin 阶段 + qCInfo(logDccUpdatePlugin) << "treeland: CSS_BeforeLogin completed, starting CSS_AfterLogin"; + QTimer::singleShot(1000, this, [this] { + doCheckSystemOnWayland(2); + }); + } + } else { + // CSS_AfterLogin 阶段完成,标记检查完成 + qCInfo(logDccUpdatePlugin) << "treeland: CSS_AfterLogin completed, mark check completed"; + m_model->setPostUpdateCheckCompleted(true); + } + } +} diff --git a/src/dcc-update-plugin/operation/updatework.h b/src/dcc-update-plugin/operation/updatework.h index 0b594ef89..17263ee61 100644 --- a/src/dcc-update-plugin/operation/updatework.h +++ b/src/dcc-update-plugin/operation/updatework.h @@ -59,6 +59,8 @@ class UpdateWorker : public QObject Q_INVOKABLE void setShutdownAndUpgrade(bool isShutdownUpdate = false); void setBackupJob(const QString& jobPath); void setDistUpgradeJob(const QString& jobPath); + void doCheckSystemOnWayland(int stage); + void setCheckSystemJob(const QString& jobPath); void updateSystemVersion(); // 更新设置-更新类型 @@ -133,6 +135,7 @@ public Q_SLOTS: void onDistUpgradeStatusChanged(const QString& status); void onInstallPackageStatusChanged(const QString& value); void onRemovePackageStatusChanged(const QString& value); + void onCheckSystemJobStatusChanged(const QString& status); Q_SIGNALS: void requestCloseTestingChannel(); @@ -163,6 +166,10 @@ public Q_SLOTS: QPointer m_backupJob; QPointer m_installPackageJob; QPointer m_removePackageJob; + QPointer m_checkSystemJob; + + int m_updateMode; + int m_currentCheckStage; // 当前 check system 阶段: 1=CSS_BeforeLogin, 2=CSS_AfterLogin }; #endif // UPDATEWORK_H diff --git a/src/dcc-update-plugin/qml/UpdateMain.qml b/src/dcc-update-plugin/qml/UpdateMain.qml index f543f44f9..5596e7c11 100644 --- a/src/dcc-update-plugin/qml/UpdateMain.qml +++ b/src/dcc-update-plugin/qml/UpdateMain.qml @@ -199,6 +199,7 @@ DccObject { updateTips: qsTr("To ensure proper functioning of your system and applications, please restart your computer after the update") btnActions: [ qsTr("Reboot now") ] updateListcheck: false + busyState: !dccData.model().postUpdateCheckCompleted onBtnClicked: function(index, updateType) { dccData.work().reStart() @@ -318,8 +319,12 @@ DccObject { if (dccData.model().isPrivateUpdate) { dccData.work().doUpgrade(updateListModels.getAllUpdateType(), true) } else { - updateSelectLoader.updateType = updateType - updateSelectLoader.active = true + if (DccApp.isTreeland()) { + dccData.work().doUpgrade(updateType, true) + } else { + updateSelectLoader.updateType = updateType + updateSelectLoader.active = true + } } } else if (index === 1) { dccData.work().reCheckWithUi(); diff --git a/src/dde-update/misc/dde-update-autostart.desktop b/src/dde-update/misc/dde-update-autostart.desktop index 80b9345e5..d4ff66cdf 100644 --- a/src/dde-update/misc/dde-update-autostart.desktop +++ b/src/dde-update/misc/dde-update-autostart.desktop @@ -2,5 +2,5 @@ Name=dde-update Type=Application NoDisplay=true -Exec=sh -c 'if [ -f /tmp/deepin_update_option.json ]; then /usr/bin/dde-update ; fi' +Exec=sh -c 'if [ -f /tmp/deepin_update_option.json ] && [ "$XDG_SESSION_TYPE" != "wayland" ]; then /usr/bin/dde-update ; fi' X-Deepin-Vendor=deepin \ No newline at end of file