/* * SPDX-FileCopyrightText: 2025 Florian RICHER * * SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include "waydroidapplicationdbusobject.h" #include #include #include #include #include #include class WaydroidApplicationDBusObject; /** * This class provides an interface to interact with the Waydroid container, * including session management and property configuration. * * @author Florian RICHER */ class WaydroidDBusObject : public QObject { Q_OBJECT QML_ELEMENT QML_SINGLETON Q_CLASSINFO("D-Bus Interface", "org.kde.plasmashell.Waydroid") public: explicit WaydroidDBusObject(QObject *parent = nullptr); /** * @enum Status * @brief Defines the possible installation statuses of the Waydroid service. */ enum Status { NotSupported = 0, NotInitialized, Initializing, Initialized, Resetting }; Q_ENUM(Status) /** * @enum SessionStatus * @brief Defines the possible states of a Waydroid session. */ enum SessionStatus { SessionStopped = 0, SessionStarting, SessionRunning }; Q_ENUM(SessionStatus) /** * @enum SystemType * @brief Defines the types of Android systems supported by Waydroid. */ enum SystemType { Vanilla = 0, ///< Vanilla Android system. Foss, ///< Free and Open Source Software variant. Gapps, ///< Variant with Google Apps included. UnknownSystemType }; Q_ENUM(SystemType) /** * @enum RomType * @brief Defines the types of ROMs supported by Waydroid. * * @todo Add OTA ROM with custom system url and vendor url */ enum RomType { Lineage = 0, ///< LineageOS ROM. Bliss ///< Bliss ROM. }; Q_ENUM(RomType) // called by QML Q_INVOKABLE void registerObject(); Q_SIGNALS: Q_SCRIPTABLE void statusChanged(); // download and total is in MB and speed in Kbps Q_SCRIPTABLE void downloadStatusChanged(double downloaded, double total, double speed); Q_SCRIPTABLE void sessionStatusChanged(); Q_SCRIPTABLE void systemTypeChanged(); Q_SCRIPTABLE void ipAddressChanged(); Q_SCRIPTABLE void androidIdChanged(); Q_SCRIPTABLE void multiWindowsChanged(); Q_SCRIPTABLE void suspendChanged(); Q_SCRIPTABLE void ueventChanged(); Q_SCRIPTABLE void applicationAdded(QDBusObjectPath path); Q_SCRIPTABLE void applicationRemoved(QDBusObjectPath path); // Use to display banner Q_SCRIPTABLE void actionFinished(const QString message); Q_SCRIPTABLE void actionFailed(const QString message); // General error Q_SCRIPTABLE void errorOccurred(const QString title, const QString message); public Q_SLOTS: Q_SCRIPTABLE int status() const; Q_SCRIPTABLE int sessionStatus() const; Q_SCRIPTABLE int systemType() const; Q_SCRIPTABLE QString ipAddress() const; Q_SCRIPTABLE QString androidId() const; Q_SCRIPTABLE bool multiWindows() const; Q_SCRIPTABLE void setMultiWindows(const bool multiWindows); Q_SCRIPTABLE bool suspend() const; Q_SCRIPTABLE void setSuspend(const bool suspend); Q_SCRIPTABLE bool uevent() const; Q_SCRIPTABLE void setUevent(const bool uevent); Q_SCRIPTABLE QList applications() const; Q_SCRIPTABLE void initialize(const int systemType, const int romType, const bool forced = false); Q_SCRIPTABLE void startSession(); Q_SCRIPTABLE void stopSession(); Q_SCRIPTABLE void resetWaydroid(); Q_SCRIPTABLE void installApk(const QString apkFile); Q_SCRIPTABLE void deleteApplication(const QString appId); Q_SCRIPTABLE void refreshSessionInfo(); Q_SCRIPTABLE void refreshAndroidId(); Q_SCRIPTABLE void refreshApplications(); private: bool m_dbusInitialized{false}; Status m_status{NotInitialized}; SessionStatus m_sessionStatus{SessionStopped}; SystemType m_systemType{UnknownSystemType}; QString m_ipAddress{""}; QString m_androidId{""}; // Waydroid props. See https://docs.waydro.id/usage/waydroid-prop-options bool m_multiWindows{false}; bool m_suspend{false}; bool m_uevent{false}; void refreshSupportsInfo(); void refreshInstallationInfo(); QCoro::Task refreshPropsInfo(); /** * @brief Executes the command to retrieve the current session status and related * information from Waydroid. * * @return A QString containing the output of the Waydroid session status command. */ QCoro::Task fetchSessionInfo(); /** * @brief Executes the command to retrieve the value of a specified property from the Waydroid container. * * @param key The key of the property to fetch. * @param defaultValue The default value to return if the property is not found or empty. * @return A QString containing the property value, or the defaultValue if not found. */ QCoro::Task fetchPropValue(const QString key, const QString defaultValue); /** * @brief Executes the command to writes a value to a specified property in the Waydroid container. * * @param key The key of the property to set. * @param value The value to write to the property. * @return A boolean indicating whether the write operation was successful. */ QCoro::Task writePropValue(const QString key, const QString value); /** * @brief Extracts text from a string using a regular expression pattern. * * @param text The text to search within. * @param regExp The regular expression pattern to use for extraction. * @return A QString containing the extracted text if a match is found; otherwise, an empty string. */ QString extractRegExp(const QString text, const QRegularExpression regExp) const; /** * @brief Checks every 500ms if the session has started. * * This function periodically checks whether a session has started. If the session starts, * it emits a "Running" signal. If the check count reaches the specified limit without * the session starting, it emits a "Stopped" signal and logs a warning message. * * @param limit The maximum number of attempts to check for session start before stopping. * @param tried The current number of attempts made to check for session start (defaults to 0). * * @todo Investigate using DBus for a cleaner implementation, potentially using the method: * id.waydro.Container /ContainerManager id.waydro.ContainerManager.Start(a{ss} session). * This would require duplicating the session start command logic from: * https://github.com/waydroid/waydroid/blob/2c41162d8bfef5bf83333a6ce4834af0c3c2b535/tools/actions/session_manager.py#L31 */ void checkSessionStarting(const int limit, const int tried = 0); QString desktopFileDirectory(); bool removeWaydroidApplications(); QCoro::Task fetchApplicationsList(); QList m_applicationObjects; };