diff options
| author | Andrew Branson <andrew.branson@cern.ch> | 2016-02-11 23:55:16 +0100 |
|---|---|---|
| committer | Andrew Branson <andrew.branson@cern.ch> | 2016-02-11 23:55:16 +0100 |
| commit | 29aaea2d80a9eb1715b6cddfac2d2aacf76358bd (patch) | |
| tree | 012795b6bec16c72f38d33cff46324c9a0225868 /rockworkd/libpebble/appmanager.cpp | |
launchpad ~mzanetti/rockwork/trunk r87
Diffstat (limited to 'rockworkd/libpebble/appmanager.cpp')
| -rw-r--r-- | rockworkd/libpebble/appmanager.cpp | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/rockworkd/libpebble/appmanager.cpp b/rockworkd/libpebble/appmanager.cpp new file mode 100644 index 0000000..04a99c7 --- /dev/null +++ b/rockworkd/libpebble/appmanager.cpp @@ -0,0 +1,255 @@ +#include <QDir> +#include <QSettings> + +#include "appmanager.h" +#include "pebble.h" + +#include "watchconnection.h" +#include "watchdatareader.h" +#include "watchdatawriter.h" +#include "uploadmanager.h" + +#include <libintl.h> + +#define SETTINGS_APP_UUID "07e0d9cb-8957-4bf7-9d42-35bf47caadfe" + +AppManager::AppManager(Pebble *pebble, WatchConnection *connection) + : QObject(pebble), + m_pebble(pebble), + m_connection(connection) +{ + QDir dataDir(m_pebble->storagePath() + "/apps/"); + if (!dataDir.exists() && !dataDir.mkpath(dataDir.absolutePath())) { + qWarning() << "could not create apps dir" << dataDir.absolutePath(); + } + qDebug() << "install apps in" << dataDir.absolutePath(); + + m_connection->registerEndpointHandler(WatchConnection::EndpointAppFetch, this, "handleAppFetchMessage"); + m_connection->registerEndpointHandler(WatchConnection::EndpointSorting, this, "sortingReply"); +} + +QList<QUuid> AppManager::appUuids() const +{ + return m_appList; +} + +//QList<QString> AppManager::appIds() const +//{ +// return m_appsIds.keys(); +//} + +AppInfo AppManager::info(const QUuid &uuid) const +{ + return m_apps.value(uuid); +} + +//AppInfo AppManager::info(const QString &id) const +//{ +// return m_appsUuids.value(m_appsIds.value(id)); +//} + +void AppManager::rescan() +{ + m_appList.clear(); + m_apps.clear(); + + AppInfo settingsApp(QUuid(SETTINGS_APP_UUID), false, gettext("Settings"), gettext("System app")); + m_appList.append(settingsApp.uuid()); + m_apps.insert(settingsApp.uuid(), settingsApp); + AppInfo watchfaces(QUuid("18e443ce-38fd-47c8-84d5-6d0c775fbe55"), false, gettext("Watchfaces"), gettext("System app")); + m_appList.append(watchfaces.uuid()); + m_apps.insert(watchfaces.uuid(), watchfaces); + if (m_pebble->capabilities().testFlag(CapabilityHealth)) { + AppInfo health(QUuid("36d8c6ed-4c83-4fa1-a9e2-8f12dc941f8c"), false, gettext("Health"), gettext("System app"), true); + m_appList.append(health.uuid()); + m_apps.insert(health.uuid(), health); + } + AppInfo music(QUuid("1f03293d-47af-4f28-b960-f2b02a6dd757"), false, gettext("Music"), gettext("System app")); + m_appList.append(music.uuid()); + m_apps.insert(music.uuid(), music); + AppInfo notifications(QUuid("b2cae818-10f8-46df-ad2b-98ad2254a3c1"), false, gettext("Notifications"), gettext("System app")); + m_appList.append(notifications.uuid()); + m_apps.insert(notifications.uuid(), notifications); + AppInfo alarms(QUuid("67a32d95-ef69-46d4-a0b9-854cc62f97f9"), false, gettext("Alarms"), gettext("System app")); + m_appList.append(alarms.uuid()); + m_apps.insert(alarms.uuid(), alarms); + AppInfo ticToc(QUuid("8f3c8686-31a1-4f5f-91f5-01600c9bdc59"), true, "Tic Toc", gettext("Default watchface")); + m_appList.append(ticToc.uuid()); + m_apps.insert(ticToc.uuid(), ticToc); + + QDir dir(m_pebble->storagePath() + "/apps/"); + qDebug() << "Scanning Apps dir" << dir.absolutePath(); + Q_FOREACH(const QString &path, dir.entryList(QDir::Dirs | QDir::Readable)) { + QString appPath = dir.absoluteFilePath(path); + if (dir.exists(path + "/appinfo.json")) { + scanApp(appPath); + } else if (QFileInfo(appPath).isFile()) { + scanApp(appPath); + } + } + + QSettings settings(m_pebble->storagePath() + "/apps.conf", QSettings::IniFormat); + QStringList storedList = settings.value("appList").toStringList(); + if (storedList.isEmpty()) { + // User did not manually sort the app list yet... We can stop here. + return; + } + // Run some sanity checks + if (storedList.count() != m_appList.count()) { + qWarning() << "Installed apps not matching order config. App sort order might be wrong."; + return; + } + foreach (const QUuid &uuid, m_appList) { + if (!storedList.contains(uuid.toString())) { + qWarning() << "Installed apps and stored config order cannot be matched. App sort order might be wrong."; + return; + } + } + // All seems fine, repopulate m_appList + m_appList.clear(); + foreach (const QString &storedId, storedList) { + m_appList.append(QUuid(storedId)); + } +} + +void AppManager::handleAppFetchMessage(const QByteArray &data) +{ + WatchDataReader reader(data); + reader.read<quint8>(); + QUuid uuid = reader.readUuid(); + quint32 appFetchId = reader.read<quint32>(); + + bool haveApp = m_apps.contains(uuid); + + AppFetchResponse response; + if (haveApp) { + response.setStatus(AppFetchResponse::StatusStart); + m_connection->writeToPebble(WatchConnection::EndpointAppFetch, response.serialize()); + } else { + qWarning() << "App with uuid" << uuid.toString() << "which is not installed."; + response.setStatus(AppFetchResponse::StatusInvalidUUID); + m_connection->writeToPebble(WatchConnection::EndpointAppFetch, response.serialize()); + emit idMismatchDetected(); + return; + } + + AppInfo appInfo = m_apps.value(uuid); + + QString binaryFile = appInfo.file(AppInfo::FileTypeApplication, m_pebble->hardwarePlatform()); + quint32 crc = appInfo.crc(AppInfo::FileTypeApplication, m_pebble->hardwarePlatform()); + qDebug() << "opened binary" << binaryFile << "for hardware" << m_pebble->hardwarePlatform() << "crc" << crc; + m_connection->uploadManager()->uploadAppBinary(appFetchId, binaryFile, crc, [this, appInfo, appFetchId](){ + qDebug() << "binary file uploaded successfully"; + + QString resourcesFile = appInfo.file(AppInfo::FileTypeResources, m_pebble->hardwarePlatform()); + quint32 crc = appInfo.crc(AppInfo::FileTypeResources, m_pebble->hardwarePlatform()); + qDebug() << "uploadign resource file" << resourcesFile; + m_connection->uploadManager()->uploadAppResources(appFetchId, resourcesFile, crc, [this, appInfo, appFetchId]() { + qDebug() << "resource file uploaded successfully"; + + QString workerFile = appInfo.file(AppInfo::FileTypeWorker, m_pebble->hardwarePlatform()); + if (!workerFile.isEmpty()) { + quint32 crc = appInfo.crc(AppInfo::FileTypeWorker, m_pebble->hardwarePlatform()); + m_connection->uploadManager()->uploadAppWorker(appFetchId, workerFile, crc, [this]() { + qDebug() << "worker file uploaded successfully"; + }); + } + }); + }); +} + +void AppManager::sortingReply(const QByteArray &data) +{ + qDebug() << "have sorting reply" << data.toHex(); +} + +void AppManager::insertAppInfo(const AppInfo &info) +{ + m_appList.append(info.uuid()); + m_apps.insert(info.uuid(), info); +// m_appsIds.insert(info.id(), info.uuid()); + emit appsChanged(); +} + +QUuid AppManager::scanApp(const QString &path) +{ + qDebug() << "scanning app" << path; + AppInfo info(path); + if (info.isValid()) { + insertAppInfo(info); + } + return info.uuid(); +} + +void AppManager::removeApp(const QUuid &uuid) +{ + m_appList.removeAll(uuid); + AppInfo info = m_apps.take(uuid); + if (!info.isValid() || info.path().isEmpty()) { + qWarning() << "App UUID not found. not removing"; + return; + + } + QDir dir(info.path()); + dir.removeRecursively(); + emit appsChanged(); +} + +void AppManager::setAppOrder(const QList<QUuid> &newList) +{ + // run some sanity checks + if (newList.count() != m_appList.count()) { + qWarning() << "Number of apps in order list is not matching installed apps."; + return; + } + foreach (const QUuid &installedUuid, m_appList) { + if (!newList.contains(installedUuid)) { + qWarning() << "App ids in order list not matching with installed apps."; + return; + } + } + if (newList.first() != QUuid(SETTINGS_APP_UUID)) { + qWarning() << "Settings app must be the first app."; + return; + } + + m_appList = newList; + QSettings settings(m_pebble->storagePath() + "/apps.conf", QSettings::IniFormat); + QStringList tmp; + foreach (const QUuid &id, m_appList) { + tmp << id.toString(); + } + settings.setValue("appList", tmp); + emit appsChanged(); + + QByteArray data; + WatchDataWriter writer(&data); + writer.write<quint8>(0x01); + writer.write<quint8>(m_appList.count()); + foreach (const QUuid &uuid, m_appList) { + writer.writeUuid(uuid); + } + + qDebug() << "writing" << data.toHex(); + m_connection->writeToPebble(WatchConnection::EndpointSorting, data); +} + +AppFetchResponse::AppFetchResponse(Status status): + m_status(status) +{ + +} + +void AppFetchResponse::setStatus(AppFetchResponse::Status status) +{ + m_status = status; +} + +QByteArray AppFetchResponse::serialize() const +{ + QByteArray ret; + WatchDataWriter writer(&ret); + writer.write<quint8>(m_command); + writer.write<quint8>(m_status); + return ret; +} |
