feat: AM loader实现启动freedesktop类型应用
AM loader可以正常启动freedesktop类型应用了 Log: AM loader实现启动freedesktop类型应用 Task: https://pms.uniontech.com/task-view-108539.html Influence: AM loader Change-Id: If56835e638ca38ed53bcc7a0dddeca47e05cc8ba
This commit is contained in:
parent
5997b3a2a1
commit
38cf02a51f
@ -1,6 +1,6 @@
|
|||||||
set(SYSTEMD_FILES
|
set(SYSTEMD_FILES
|
||||||
org.deskspec.application.instance@.service
|
org.desktopspec.application.instance@.service
|
||||||
org.deskspec.application.manager.service
|
org.desktopspec.application.manager.service
|
||||||
)
|
)
|
||||||
|
|
||||||
install(FILES ${SYSTEMD_FILES} DESTINATION lib/systemd/user/)
|
install(FILES ${SYSTEMD_FILES} DESTINATION lib/systemd/user/)
|
||||||
|
@ -3,6 +3,6 @@ Description=Deepin Application Manager service
|
|||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=DBus
|
Type=DBus
|
||||||
BusName=org.deskspec.ApplicationManager
|
BusName=org.desktopspec.ApplicationManager
|
||||||
ExecStart=/usr/bin/deepin-application-service
|
ExecStart=/usr/bin/deepin-application-manager
|
||||||
Slice=services.slice
|
Slice=services.slice
|
@ -18,6 +18,10 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QProcess>
|
||||||
|
#include <QDir>
|
||||||
|
|
||||||
#include "../modules/methods/basic.h"
|
#include "../modules/methods/basic.h"
|
||||||
#include "../modules/methods/instance.hpp"
|
#include "../modules/methods/instance.hpp"
|
||||||
#include "../modules/methods/quit.hpp"
|
#include "../modules/methods/quit.hpp"
|
||||||
@ -40,25 +44,16 @@ struct App {
|
|||||||
std::string id;
|
std::string id;
|
||||||
};
|
};
|
||||||
|
|
||||||
static App parseApp(const std::string& app)
|
static App parseApp(const QString& app)
|
||||||
{
|
{
|
||||||
std::vector<std::string> strings;
|
QStringList values = app.split('/', QString::SkipEmptyParts);
|
||||||
std::istringstream stream(app);
|
qInfo() << "app:" << app << ", values size:" << values.size();
|
||||||
std::string s;
|
|
||||||
while (getline(stream, s, '/')) {
|
|
||||||
if (s.empty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
strings.push_back(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
App result;
|
App result;
|
||||||
if (strings.size() == 3) {
|
if (values.size() == 3) {
|
||||||
result.prefix = strings[0];
|
result.prefix = values.at(0).toStdString();
|
||||||
result.type = strings[1];
|
result.type = values.at(1).toStdString();
|
||||||
result.id = strings[2];
|
result.id = values.at(2).toStdString();
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,12 +72,51 @@ void sig_handler(int num)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int runLinglong(void* _arg)
|
// TODO: startManager合并流程?
|
||||||
|
int childFreedesktop(Methods::Task* task, std::string path)
|
||||||
{
|
{
|
||||||
return 0;
|
prctl(PR_SET_PDEATHSIG, SIGKILL);
|
||||||
|
prctl(PR_SET_PDEATHSIG, SIGTERM);
|
||||||
|
prctl(PR_SET_PDEATHSIG, SIGHUP);
|
||||||
|
|
||||||
|
DesktopDeconstruction dd(path);
|
||||||
|
dd.beginGroup("Desktop Entry");
|
||||||
|
std::cout << dd.value<std::string>("Exec") << std::endl;
|
||||||
|
|
||||||
|
QStringList envs;
|
||||||
|
for (auto it = task->environments.begin(); it != task->environments.end(); ++it) {
|
||||||
|
envs.append(it.key() + "=" + it.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
int child(Methods::Task* task, std::string path)
|
QStringList exeArgs;
|
||||||
|
exeArgs << QString::fromStdString(dd.value<std::string>("Exec")).split(" ");
|
||||||
|
|
||||||
|
QString exec = exeArgs[0];
|
||||||
|
exeArgs.removeAt(0);
|
||||||
|
|
||||||
|
pid_t pid = fork();
|
||||||
|
if (pid == -1) {
|
||||||
|
perror("fork()");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pid == 0) {
|
||||||
|
// 子进程
|
||||||
|
QProcess process;
|
||||||
|
qInfo() << "exec:" << exec;
|
||||||
|
qInfo() << "exeArgs:" << exeArgs;
|
||||||
|
process.setWorkingDirectory(QDir::homePath());
|
||||||
|
process.setEnvironment(envs);
|
||||||
|
process.start(exec, exeArgs);
|
||||||
|
process.waitForFinished(-1);
|
||||||
|
process.close();
|
||||||
|
qInfo() << "process finish";
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
int childLinglong(Methods::Task* task, std::string path)
|
||||||
{
|
{
|
||||||
prctl(PR_SET_PDEATHSIG, SIGKILL);
|
prctl(PR_SET_PDEATHSIG, SIGKILL);
|
||||||
prctl(PR_SET_PDEATHSIG, SIGTERM);
|
prctl(PR_SET_PDEATHSIG, SIGTERM);
|
||||||
@ -179,6 +213,12 @@ int child(Methods::Task* task, std::string path)
|
|||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int childAndroid(Methods::Task* task, std::string path)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#define DAM_TASK_HASH "DAM_TASK_HASH"
|
#define DAM_TASK_HASH "DAM_TASK_HASH"
|
||||||
#define DAM_TASK_TYPE "DAM_TASK_TYPE"
|
#define DAM_TASK_TYPE "DAM_TASK_TYPE"
|
||||||
|
|
||||||
@ -228,19 +268,23 @@ int main(int argc, char* argv[])
|
|||||||
result = client.get(instanceArray);
|
result = client.get(instanceArray);
|
||||||
Methods::Task task;
|
Methods::Task task;
|
||||||
Methods::fromJson(result, task); // fromJson TODO 数据解析异常
|
Methods::fromJson(result, task); // fromJson TODO 数据解析异常
|
||||||
qWarning() << "[result] " << result;
|
qInfo() << "[Task] " << result;
|
||||||
|
|
||||||
// 校验task内容
|
// 校验task内容
|
||||||
App app = parseApp(task.runId.toStdString());
|
App app = parseApp(task.runId);
|
||||||
|
qInfo() << "[App] "
|
||||||
|
<< "prefix:" << QString::fromStdString(app.prefix)
|
||||||
|
<< "type:" << QString::fromStdString(app.type)
|
||||||
|
<< "id:" << QString::fromStdString(app.id);
|
||||||
if (task.id.isEmpty() || app.id.empty() || app.type.empty() || app.prefix.empty()) {
|
if (task.id.isEmpty() || app.id.empty() || app.type.empty() || app.prefix.empty()) {
|
||||||
std::cout << "get task error" << std::endl;
|
std::cout << "get task error" << std::endl;
|
||||||
return -4;
|
return -4;
|
||||||
}
|
}
|
||||||
|
if (app.prefix != "freedesktop"
|
||||||
std::string path{ "/usr/share/applications/" + app.id + ".desktop" };
|
&& app.prefix != "linglong"
|
||||||
if (app.type == "user") {
|
&& app.prefix != "android") {
|
||||||
struct passwd* user = getpwuid(getuid());
|
qWarning() << "error app prefix :" << QString::fromStdString(app.type);
|
||||||
path = std::string(user->pw_dir) + "/.local/share/applications/" + app.id + ".desktop";
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_attr_t attr;
|
pthread_attr_t attr;
|
||||||
@ -251,27 +295,39 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
/* 先将SIGCHLD信号阻塞 保证在子进程结束前设置父进程的捕捉函数 */
|
/* 先将SIGCHLD信号阻塞 保证在子进程结束前设置父进程的捕捉函数 */
|
||||||
sigset_t nmask, omask;
|
sigset_t nmask, omask;
|
||||||
sigemptyset(&nmask);
|
// sigemptyset(&nmask);
|
||||||
sigaddset(&nmask, SIGCHLD);
|
// sigaddset(&nmask, SIGCHLD);
|
||||||
sigprocmask(SIG_BLOCK, &nmask, &omask);
|
// sigprocmask(SIG_BLOCK, &nmask, &omask);
|
||||||
|
|
||||||
//char* stack = (char*) malloc(stack_size);
|
//char* stack = (char*) malloc(stack_size);
|
||||||
//pid_t pid = clone(child, stack + stack_size, CLONE_NEWPID | SIGCHLD, static_cast<void*>(&task));
|
//pid_t pid = clone(child, stack + stack_size, CLONE_NEWPID | SIGCHLD, static_cast<void*>(&task));
|
||||||
pid_t pid = child(&task, path);
|
pid_t pid = -1;
|
||||||
|
if (app.prefix == "freedesktop") {
|
||||||
|
pid = childFreedesktop(&task, task.filePath.toStdString());
|
||||||
|
} else if (app.prefix == "linglong") {
|
||||||
|
pid = childLinglong(&task, task.filePath.toStdString());
|
||||||
|
} else if (app.prefix == "android") {
|
||||||
|
pid = childAndroid(&task, task.filePath.toStdString());
|
||||||
|
} else {
|
||||||
|
qWarning() << "error app prefix:" << QString::fromStdString(app.prefix);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: 启动线程,创建新的连接去接受服务器的消息
|
// TODO: 启动线程,创建新的连接去接受服务器的消息
|
||||||
|
|
||||||
|
// TODO:信号处理有问题
|
||||||
/* 设置捕捉函数 */
|
/* 设置捕捉函数 */
|
||||||
struct sigaction sig;
|
// struct sigaction sig;
|
||||||
sig.sa_handler = sig_handler;
|
// sig.sa_handler = sig_handler;
|
||||||
sigemptyset(&sig.sa_mask);
|
// sigemptyset(&sig.sa_mask);
|
||||||
sig.sa_flags = 0;
|
// sig.sa_flags = 0;
|
||||||
sigaction(SIGCHLD, &sig, NULL);
|
// sigaction(SIGCHLD, &sig, NULL);
|
||||||
/* 然后再unblock */
|
/* 然后再unblock */
|
||||||
sigdelset(&omask, SIGCHLD);
|
// sigdelset(&omask, SIGCHLD);
|
||||||
sigprocmask(SIG_SETMASK, &omask, NULL);
|
// sigprocmask(SIG_SETMASK, &omask, NULL);
|
||||||
|
|
||||||
int exitCode;
|
int exitCode;
|
||||||
waitpid(pid, &exitCode, 0);
|
waitpid(pid, &exitCode, 0);
|
||||||
|
qInfo() << "app exitCode:" << exitCode;
|
||||||
|
|
||||||
Methods::Quit quit;
|
Methods::Quit quit;
|
||||||
quit.code = exitCode;
|
quit.code = exitCode;
|
||||||
|
@ -18,6 +18,7 @@ namespace Methods
|
|||||||
QString runId;
|
QString runId;
|
||||||
QString type{"task"};
|
QString type{"task"};
|
||||||
QString date;
|
QString date;
|
||||||
|
QString filePath;
|
||||||
QList<QString> arguments;
|
QList<QString> arguments;
|
||||||
QMap<QString, QString> environments;
|
QMap<QString, QString> environments;
|
||||||
};
|
};
|
||||||
@ -36,7 +37,8 @@ namespace Methods
|
|||||||
QJsonObject obj = {
|
QJsonObject obj = {
|
||||||
{"type", task.type},
|
{"type", task.type},
|
||||||
{"id", task.id},
|
{"id", task.id},
|
||||||
{"run_id", task.runId},
|
{"runId", task.runId},
|
||||||
|
{"filePath", task.filePath},
|
||||||
{"date", task.date},
|
{"date", task.date},
|
||||||
{"arguments", argArray},
|
{"arguments", argArray},
|
||||||
{"environments", QJsonObject::fromVariantMap(envsMap)}
|
{"environments", QJsonObject::fromVariantMap(envsMap)}
|
||||||
@ -51,26 +53,32 @@ namespace Methods
|
|||||||
qWarning() << "fromJson task failed";
|
qWarning() << "fromJson task failed";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject obj = doc.object();
|
QJsonObject obj = doc.object();
|
||||||
if (!obj.contains("id") || !obj.contains("runId") || !obj.contains("date") \
|
if (obj.contains("id")) {
|
||||||
|| !obj.contains("arguments") || !obj.contains("environments")) {
|
task.id = obj.value("id").toString();
|
||||||
qWarning() << "id runId date arguments environments not exist in task array";
|
}
|
||||||
return;
|
if (obj.contains("runId")) {
|
||||||
|
task.runId = obj.value("runId").toString();
|
||||||
|
}
|
||||||
|
if (obj.contains("filePath")) {
|
||||||
|
task.filePath = obj.value("filePath").toString();
|
||||||
|
}
|
||||||
|
if (obj.contains("date")) {
|
||||||
|
task.date = obj.value("date").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
task.id = obj.value("id").toString();
|
if (obj.contains("arguments")) {
|
||||||
task.runId = obj.value("runId").toString();
|
|
||||||
task.date = obj.value("date").toString();
|
|
||||||
for (auto arg : obj.value("arguments").toArray()) {
|
for (auto arg : obj.value("arguments").toArray()) {
|
||||||
task.arguments.append(arg.toString());
|
task.arguments.append(arg.toString());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (obj.contains("environments")) {
|
||||||
QVariantMap envsMap = obj.value("environments").toObject().toVariantMap();
|
QVariantMap envsMap = obj.value("environments").toObject().toVariantMap();
|
||||||
for (auto it = envsMap.constBegin(); it != envsMap.constEnd(); ++it) {
|
for (auto it = envsMap.constBegin(); it != envsMap.constEnd(); ++it) {
|
||||||
task.environments.insert(it.key(), it.value().toString());
|
task.environments.insert(it.key(), it.value().toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} // namespace Methods
|
} // namespace Methods
|
||||||
|
|
||||||
#endif /* B0B88BD6_CF1E_4E87_926A_E6DBE6B9B19C */
|
#endif /* B0B88BD6_CF1E_4E87_926A_E6DBE6B9B19C */
|
||||||
|
@ -68,8 +68,9 @@ public:
|
|||||||
emit q_ptr->taskFinished(p->exitCode());
|
emit q_ptr->taskFinished(p->exitCode());
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
qInfo() << "app manager load service:" << QString("org.desktopspec.application.instance@%1.service").arg(m_id);
|
||||||
QDBusInterface systemd("org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager");
|
QDBusInterface systemd("org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager");
|
||||||
QDBusReply<void> reply = systemd.call("StartUnit", QString("org.deskspec.application.instance@%1.service").arg(m_id), "replace-irreversibly");
|
QDBusReply<void> reply = systemd.call("StartUnit", QString("org.desktopspec.application.instance@%1.service").arg(m_id), "replace-irreversibly");
|
||||||
if (!reply.isValid()) {
|
if (!reply.isValid()) {
|
||||||
qInfo() << reply.error();
|
qInfo() << reply.error();
|
||||||
q_ptr->deleteLater();
|
q_ptr->deleteLater();
|
||||||
@ -82,7 +83,7 @@ public:
|
|||||||
#ifdef LOADER_PATH
|
#ifdef LOADER_PATH
|
||||||
#else
|
#else
|
||||||
QDBusInterface systemd("org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager");
|
QDBusInterface systemd("org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager");
|
||||||
qInfo() << systemd.call("StopUnit", QString("org.deskspec.application.instance@%1.service").arg(m_id), "replace-irreversibly");
|
qInfo() << systemd.call("StopUnit", QString("org.desktopspec.application.instance@%1.service").arg(m_id), "replace-irreversibly");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,6 +147,7 @@ Methods::Task ApplicationInstance::taskInfo() const
|
|||||||
Methods::Task task;
|
Methods::Task task;
|
||||||
task.id = d->m_id;
|
task.id = d->m_id;
|
||||||
task.runId = d->application->id();
|
task.runId = d->application->id();
|
||||||
|
task.filePath = d->application->filePath();
|
||||||
task.date = QString::number(startuptime());
|
task.date = QString::number(startuptime());
|
||||||
task.arguments = m_files;
|
task.arguments = m_files;
|
||||||
|
|
||||||
|
@ -90,8 +90,11 @@ void ApplicationManagerPrivate::recvClientData(int socket, const std::vector<cha
|
|||||||
result.state = false;
|
result.state = false;
|
||||||
// std::lock_guard<std::mutex> lock(task_mutex);
|
// std::lock_guard<std::mutex> lock(task_mutex);
|
||||||
for (auto it = tasks.begin(); it != tasks.end(); ++it) {
|
for (auto it = tasks.begin(); it != tasks.end(); ++it) {
|
||||||
|
if (registe.hash == QString::fromStdString(it->first)) {
|
||||||
result.state = true;
|
result.state = true;
|
||||||
result.hash = QString::fromStdString(it->first);
|
result.hash = registe.hash;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Methods::toJson(tmpArray, result);
|
Methods::toJson(tmpArray, result);
|
||||||
write(socket, tmpArray.toStdString());
|
write(socket, tmpArray.toStdString());
|
||||||
@ -199,6 +202,7 @@ QList<QDBusObjectPath> ApplicationManager::GetInstances(const QString &id)
|
|||||||
*/
|
*/
|
||||||
QDBusObjectPath ApplicationManager::Launch(const QString &id, QStringList files)
|
QDBusObjectPath ApplicationManager::Launch(const QString &id, QStringList files)
|
||||||
{
|
{
|
||||||
|
qInfo() << "Launch " << id;
|
||||||
Q_D(ApplicationManager);
|
Q_D(ApplicationManager);
|
||||||
if (!d->checkDMsgUid())
|
if (!d->checkDMsgUid())
|
||||||
return {};
|
return {};
|
||||||
|
@ -90,6 +90,11 @@ int main(int argc, char *argv[])
|
|||||||
QDBusConnection::sessionBus().registerObject(app->path().path(), "org.desktopspec.Application", app.get());
|
QDBusConnection::sessionBus().registerObject(app->path().path(), "org.desktopspec.Application", app.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const QSharedPointer<Application> &app : apps) {
|
||||||
|
qInfo() << "appId - " << app->id();
|
||||||
|
qInfo() << "appFilePath - " << app->filePath();
|
||||||
|
}
|
||||||
|
|
||||||
ApplicationManager::instance()->addApplication(apps);
|
ApplicationManager::instance()->addApplication(apps);
|
||||||
|
|
||||||
ApplicationManager::instance()->launchAutostartApps();
|
ApplicationManager::instance()->launchAutostartApps();
|
||||||
|
Loading…
Reference in New Issue
Block a user