shift-shell/components/waydroidintegrationplugin/waydroidstate.h
Florian RICHER 14839c4389 kcm: Implement minimal Waydroid support
I prefer create MR now to avoid biggest merge request.

It add minimalist implementation: 
- First configuration of Waydroid
- Stop / Start Waydroid session
- Configure properties of Waydroid
- Display current ip of Waydroid

| Not installed | First initialization | initializing | SessionNotStarted | SessionStarting | SessionStarted |
| ------ | ------ | ------ | ------ | ------ | ------ |
| ![Copie_d_écran_20250705_162112](/uploads/66844057ee6c955803288993809616fa/Copie_d_écran_20250705_162112.png) | ![Copie_d_écran_20250707_234822](/uploads/133779f8d4a70551a321938a7193aa3d/Copie_d_écran_20250707_234822.png) | ![Copie_d_écran_20250707_234829](/uploads/bacecd42875e3afd48dba2f9472b0f13/Copie_d_écran_20250707_234829.png) | ![Copie_d_écran_20250707_234908](/uploads/c6eff9833e33f30797088e327fcf6ea3/Copie_d_écran_20250707_234908.png) | ![Copie_d_écran_20250707_234919](/uploads/1927e2334d7e3b5790e5fab9037feff7/Copie_d_écran_20250707_234919.png) | ![Copie_d_écran_20250707_235239](/uploads/9be45b0a7b5f988de0e9ac297a2447c8/Copie_d_écran_20250707_235239.png) |

Linked to https://invent.kde.org/teams/plasma-mobile/issues/-/issues/307

**Note for Reviewer**: In my local environment, i need to add manually the KAuth files otherwise polkit not recognize the implementation.

```
sudo cp ~/kde/usr/share/dbus-1/system-services/org.kde.plasma.mobileshell.waydroidhelper.service /usr/share/dbus-1/system-services/
sudo cp ~/kde/usr/share/dbus-1/system.d/org.kde.plasma.mobileshell.waydroidhelper.conf /usr/share/dbus-1/system.d/
sudo cp ~/kde/usr/share/polkit-1/actions/org.kde.plasma.mobileshell.waydroidhelper.policy /usr/share/polkit-1/actions/
```
2025-07-10 12:00:41 -04:00

178 lines
6.1 KiB
C++

/*
* SPDX-FileCopyrightText: 2025 Florian RICHER <florian.richer@protonmail.com>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include <QObject>
#include <qqmlregistration.h>
#include <qtmetamacros.h>
/**
* This class provides an interface to interact with the Waydroid container,
* including session management and property configuration.
*
* @author Florian RICHER <florian.richer@protonmail.com>
*/
class WaydroidState : public QObject
{
Q_OBJECT
QML_ELEMENT
QML_SINGLETON
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
Q_PROPERTY(SessionStatus sessionStatus READ sessionStatus NOTIFY sessionStatusChanged)
Q_PROPERTY(QString ipAddress READ ipAddress NOTIFY ipAddressChanged)
Q_PROPERTY(QString errorTitle READ errorTitle NOTIFY errorTitleChanged)
Q_PROPERTY(QString errorMessage READ errorMessage NOTIFY errorMessageChanged)
Q_PROPERTY(bool multiWindows READ multiWindows WRITE setMultiWindows NOTIFY multiWindowsChanged)
Q_PROPERTY(bool suspend READ suspend WRITE setSuspend NOTIFY suspendChanged)
Q_PROPERTY(bool uevent READ uevent WRITE setUevent NOTIFY ueventChanged)
public:
WaydroidState(QObject *parent = nullptr);
/**
* @enum Status
* @brief Defines the possible installation statuses of the Waydroid service.
*/
enum Status {
NotSupported = 0,
NotInitialized,
Initializing,
Initialized
};
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.
};
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)
Q_INVOKABLE void refreshSupportsInfo();
Q_INVOKABLE void refreshSessionInfo();
Q_INVOKABLE void refreshPropsInfo();
Q_INVOKABLE void resetError();
Q_INVOKABLE void initialize(const SystemType systemType, const RomType romType, const bool forced = false);
Q_INVOKABLE void startSession();
Q_INVOKABLE void stopSession();
Q_INVOKABLE void copyToClipboard(const QString text);
Status status() const;
SessionStatus sessionStatus() const;
QString ipAddress() const;
QString errorTitle() const;
QString errorMessage() const;
bool multiWindows() const;
void setMultiWindows(const bool multiWindows);
bool suspend() const;
void setSuspend(const bool suspend);
bool uevent() const;
void setUevent(const bool uevent);
Q_SIGNALS:
void statusChanged();
void sessionStatusChanged();
void ipAddressChanged();
void multiWindowsChanged();
void suspendChanged();
void ueventChanged();
void errorTitleChanged();
void errorMessageChanged();
private:
Status m_status{NotInitialized};
SessionStatus m_sessionStatus{SessionStopped};
QString m_ipAddress{""};
QString m_errorTitle{""};
QString m_errorMessage{""};
// Waydroid props. See https://docs.waydro.id/usage/waydroid-prop-options
bool m_multiWindows{false};
bool m_suspend{false};
bool m_uevent{false};
/**
* @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.
*/
QString 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.
*/
QString 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.
*/
bool 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);
};