summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/b2qt-flashing-wizard/sync.profile3
-rw-r--r--src/b2qt-update-application/.gitignore4
-rw-r--r--src/b2qt-update-application/b2qt-update-application.pro35
-rw-r--r--src/b2qt-update-application/filewrapper.cpp53
-rw-r--r--src/b2qt-update-application/filewrapper.h40
-rw-r--r--src/b2qt-update-application/main.cpp204
-rw-r--r--src/b2qt-update-application/tar.cpp309
-rw-r--r--src/b2qt-update-application/tar.h99
-rw-r--r--src/b2qt-update-application/update.cpp202
-rw-r--r--src/b2qt-update-application/update.h50
-rw-r--r--src/b2qt-update-util/.gitignore4
-rw-r--r--src/b2qt-update-util/b2qt-update-util.pro23
-rw-r--r--src/b2qt-update-util/main.cpp144
-rw-r--r--src/doc/config/b2qt-project.qdocconf21
-rw-r--r--src/doc/src/devices/qtee-architech-tibidabo.qdoc4
-rw-r--r--src/doc/src/devices/qtee-bd-sl-imx6.qdoc2
-rw-r--r--src/doc/src/devices/qtee-beaglebone-black.qdoc4
-rw-r--r--src/doc/src/devices/qtee-imx53.qdoc2
-rw-r--r--src/doc/src/devices/qtee-kontron-smarc-samx6i.qdoc2
-rw-r--r--src/doc/src/devices/qtee-raspberry-pi.qdoc4
-rw-r--r--src/doc/src/devices/qtee-sabre-sd-imx6.qdoc23
-rw-r--r--src/doc/src/devices/qtee-supported-devices.qdoc47
-rw-r--r--src/doc/src/devices/qtee-toradex-apalis.qdoc4
-rw-r--r--src/doc/src/devices/qtee-toradex-colibri-imx6.qdoc4
-rw-r--r--src/doc/src/devices/qtee-toradex-colibri-vf.qdoc4
-rw-r--r--src/doc/src/qtee-changelog.qdoc2
-rw-r--r--src/doc/src/qtee-custom-embedded-linux.qdoc21
-rw-r--r--src/doc/src/qtee-customization.qdoc2
-rw-r--r--src/doc/src/qtee-index.qdoc22
-rw-r--r--src/doc/src/qtee-static-linking.qdoc226
-rw-r--r--src/doc/src/shared/b2qt-post-install-setup.qdocinc6
-rw-r--r--src/doppelganger/appops.cpp50
-rw-r--r--src/doppelganger/appops.h29
-rw-r--r--src/doppelganger/doppelganger.pro22
-rw-r--r--src/doppelganger/main.cpp36
-rw-r--r--src/doppelganger/permissioncontroller.cpp38
-rw-r--r--src/doppelganger/permissioncontroller.h35
-rw-r--r--src/doppelganger/powermanager.cpp88
-rw-r--r--src/doppelganger/powermanager.h62
-rw-r--r--src/doppelganger/schedulingpolicyservice.cpp88
-rw-r--r--src/doppelganger/schedulingpolicyservice.h44
-rw-r--r--src/imports/nativemedia/BufferQueue.cpp1061
-rw-r--r--src/imports/nativemedia/BufferQueue.h490
-rw-r--r--src/imports/nativemedia/SurfaceTexture.cpp23
-rw-r--r--src/imports/nativemedia/SurfaceTexture.h23
-rw-r--r--src/imports/nativemedia/SurfaceTexture_4_0.cpp1236
-rw-r--r--src/imports/nativemedia/SurfaceTexture_4_0.h517
-rw-r--r--src/imports/nativemedia/SurfaceTexture_4_1.cpp866
-rw-r--r--src/imports/nativemedia/SurfaceTexture_4_1.h420
-rw-r--r--src/imports/nativemedia/main.cpp73
-rw-r--r--src/imports/nativemedia/nativemedia.pro21
-rw-r--r--src/imports/nativemedia/omx.cpp666
-rw-r--r--src/imports/nativemedia/omxmodule.cpp37
-rw-r--r--src/imports/nativemedia/omxnode.cpp204
-rw-r--r--src/imports/nativemedia/omxnode.h129
-rw-r--r--src/imports/nativemedia/omxplayer.h42
-rw-r--r--src/imports/nativemedia/qmldir2
-rw-r--r--src/imports/nativemedia/test.qml53
-rw-r--r--src/plugins/plugins.pro3
-rw-r--r--src/plugins/sensors/eandroid/eandroid.pro30
-rw-r--r--src/plugins/sensors/eandroid/eandroidaccelerometer.cpp38
-rw-r--r--src/plugins/sensors/eandroid/eandroidaccelerometer.h38
-rw-r--r--src/plugins/sensors/eandroid/eandroidambientlightsensor.cpp47
-rw-r--r--src/plugins/sensors/eandroid/eandroidambientlightsensor.h38
-rw-r--r--src/plugins/sensors/eandroid/eandroidbasesensor.cpp59
-rw-r--r--src/plugins/sensors/eandroid/eandroidbasesensor.h40
-rw-r--r--src/plugins/sensors/eandroid/eandroidgyroscope.cpp40
-rw-r--r--src/plugins/sensors/eandroid/eandroidgyroscope.h38
-rw-r--r--src/plugins/sensors/eandroid/eandroidlight.cpp36
-rw-r--r--src/plugins/sensors/eandroid/eandroidlight.h38
-rw-r--r--src/plugins/sensors/eandroid/eandroidmagnetometer.cpp57
-rw-r--r--src/plugins/sensors/eandroid/eandroidmagnetometer.h38
-rw-r--r--src/plugins/sensors/eandroid/eandroidrotationsensor.cpp42
-rw-r--r--src/plugins/sensors/eandroid/eandroidrotationsensor.h38
-rw-r--r--src/plugins/sensors/eandroid/eandroidsensordevice.cpp212
-rw-r--r--src/plugins/sensors/eandroid/eandroidsensordevice.h99
-rw-r--r--src/plugins/sensors/eandroid/main.cpp142
-rw-r--r--src/plugins/sensors/eandroid/plugin.json1
-rw-r--r--src/plugins/sensors/sensors.pro3
-rw-r--r--src/qconnectivity/main.cpp476
-rw-r--r--src/qconnectivity/qconnectivity.pro13
-rw-r--r--src/qt_hw_init/main.cpp30
-rw-r--r--src/qt_hw_init/qt_hw_init.pro8
-rw-r--r--src/src.pro7
-rw-r--r--src/utils/b2qtdevice.cpp241
-rw-r--r--src/utils/utils.pro2
-rw-r--r--src/wifi/qwificontroller.cpp251
-rw-r--r--src/wifi/qwificontroller_p.h33
-rw-r--r--src/wifi/qwifidevice.cpp80
-rw-r--r--src/wifi/qwifidevice.h7
-rw-r--r--src/wifi/qwifielinux.cpp337
-rw-r--r--src/wifi/qwifielinux_p.h42
-rw-r--r--src/wifi/qwifimanager.cpp56
-rw-r--r--src/wifi/qwifimanager_p.h1
-rw-r--r--src/wifi/qwifinetworklistmodel.cpp4
-rw-r--r--src/wifi/qwifisupplicant.cpp420
-rw-r--r--src/wifi/qwifisupplicant_p.h (renamed from src/wifi/qwifiutils_p.h)38
-rw-r--r--src/wifi/qwifiutils.cpp135
-rw-r--r--src/wifi/wifi.pro23
99 files changed, 826 insertions, 10380 deletions
diff --git a/src/b2qt-flashing-wizard/sync.profile b/src/b2qt-flashing-wizard/sync.profile
new file mode 100644
index 0000000..8d7f77e
--- /dev/null
+++ b/src/b2qt-flashing-wizard/sync.profile
@@ -0,0 +1,3 @@
+%dependencies = (
+ "qtbase" => "",
+);
diff --git a/src/b2qt-update-application/.gitignore b/src/b2qt-update-application/.gitignore
deleted file mode 100644
index d2a78c0..0000000
--- a/src/b2qt-update-application/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-Makefile
-b2qt-update-application
-moc_*.cpp
-*.o
diff --git a/src/b2qt-update-application/b2qt-update-application.pro b/src/b2qt-update-application/b2qt-update-application.pro
deleted file mode 100644
index 51fc06f..0000000
--- a/src/b2qt-update-application/b2qt-update-application.pro
+++ /dev/null
@@ -1,35 +0,0 @@
-CONFIG += c++11
-QT = core network
-SOURCES += \
- main.cpp \
- tar.cpp \
- filewrapper.cpp \
- update.cpp
-
-HEADERS += \
- tar.h \
- filewrapper.h \
- update.h
-
-LIBS += -lcrypto
-INSTALLS += target
-target.path = /usr/bin
-
-# Find out git hash
-unix:system(which git):HAS_GIT=TRUE
-win32:system(where git.exe):HAS_GIT=TRUE
-contains(HAS_GIT, TRUE) {
- GIT_HASH=$$system(git log -1 --format=%H)
- !system(git diff-index --quiet HEAD): GIT_HASH="$$GIT_HASH-dirty"
- GIT_VERSION=$$system(git describe --tags --exact-match)
- isEmpty(GIT_VERSION) : GIT_VERSION="unknown"
-} else {
- GIT_HASH="unknown"
- GIT_VERSION="unknown"
-}
-
-isEmpty(GIT_VERSION) : error("No suitable tag found")
-isEmpty(GIT_HASH) : error("No hash available")
-
-DEFINES+="GIT_HASH=\\\"$$GIT_HASH\\\""
-DEFINES+="GIT_VERSION=\\\"$$GIT_VERSION\\\""
diff --git a/src/b2qt-update-application/filewrapper.cpp b/src/b2qt-update-application/filewrapper.cpp
deleted file mode 100644
index 6b4a759..0000000
--- a/src/b2qt-update-application/filewrapper.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://qt.digia.com/
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://qt.digia.com/
-**
-****************************************************************************/
-
-#include "filewrapper.h"
-#include <QDebug>
-#include <QTimer>
-
-FileWrapper::FileWrapper(const QString &fileName, QObject *parent)
- : QFile(fileName, parent)
- , mTimer(new QTimer(this))
-{
- mTimer->setInterval(50);
- connect(mTimer, &QTimer::timeout, this, &FileWrapper::emitReadyRead);
-}
-
-FileWrapper::~FileWrapper()
-{
-}
-
-bool FileWrapper::open(OpenMode mode)
-{
- bool rc = QFile::open(mode);
- if (rc) {
- mTimer->start();
- }
- return rc;
-}
-
-void FileWrapper::emitReadyRead()
-{
- if (!atEnd()) {
- emit readyRead();
- } else {
- mTimer->stop();
- close();
- }
-}
diff --git a/src/b2qt-update-application/filewrapper.h b/src/b2qt-update-application/filewrapper.h
deleted file mode 100644
index fc8a977..0000000
--- a/src/b2qt-update-application/filewrapper.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://qt.digia.com/
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://qt.digia.com/
-**
-****************************************************************************/
-
-#ifndef FILEWRAPPER_H
-#define FILEWRAPPER_H
-
-#include <QFile>
-class QTimer;
-
-class FileWrapper : public QFile
-{
- Q_OBJECT
-
-public:
- FileWrapper(const QString &fileName, QObject *parent = 0);
- virtual ~FileWrapper();
- bool open(OpenMode mode);
-
-private:
- void emitReadyRead();
- QTimer *mTimer;
-};
-
-#endif // FILEWRAPPER_H
diff --git a/src/b2qt-update-application/main.cpp b/src/b2qt-update-application/main.cpp
deleted file mode 100644
index 353edd9..0000000
--- a/src/b2qt-update-application/main.cpp
+++ /dev/null
@@ -1,204 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://qt.digia.com/
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://qt.digia.com/
-**
-****************************************************************************/
-
-#include <QCoreApplication>
-#include <QProcess>
-#include <QDebug>
-#include <QFile>
-#include <QDir>
-#include <unistd.h>
-#include <sys/reboot.h>
-#include <QNetworkAccessManager>
-#include <QUrl>
-#include <QNetworkRequest>
-#include <QNetworkReply>
-#include "update.h"
-#include "filewrapper.h"
-
-#define UPDATE_MOUNTPOINT "/mnt/update"
-
-QStringList mounts;
-
-void cleanup()
-{
- foreach (const QString &m, mounts) {
- QProcess::execute("umount", QStringList() << m);
- }
- mounts.clear();
-}
-
-void error(const QString &message)
-{
- fprintf(stderr, "%s\n", message.toLocal8Bit().constData());
- cleanup();
- exit(1);
-}
-
-bool execute(const QString &binary, const QStringList &arguments)
-{
- int rc = QProcess::execute(binary, arguments);
- if (rc != 0)
- error("Failed to execute command '" + binary + " " + arguments.join(" "));
- return rc == 0;
-}
-
-bool mount(const QString &device, const QString &mountpoint, const QString &arguments = QString())
-{
- QStringList tmp;
- if (!arguments.isEmpty())
- tmp << "-o" << arguments;
-
- if (!execute("mount", QStringList() << tmp << device << mountpoint))
- return false;
-
- if (!arguments.contains("remount"))
- mounts << mountpoint;
- return true;
-}
-
-QByteArray readAll(const QString &fileName)
-{
- QFile f(fileName);
- if (!f.open(QFile::ReadOnly)) {
- qWarning() << "Could not read" << fileName;
- return QByteArray();
- }
-
- return f.readAll();
-}
-
-bool writeAll(const QString &fileName, const QByteArray &content)
-{
- QFile f(fileName);
- if (!f.open(QFile::WriteOnly)) {
- qWarning() << "Could not write" << fileName;
- return false;
- }
- if (f.write(content) != content.size()) {
- qWarning() << "write size mismatch";
- return false;
- }
- f.close();
- return true;
-}
-
-QStringList find_usb_storage()
-{
- QStringList rc;
- QDir d("/sys/dev/block");
-
- foreach (QString s, d.entryList()) {
- QFileInfo fi(d.absoluteFilePath(s));
- QString path = fi.canonicalFilePath();
- if (path.contains("/usb"))
- rc += path.mid(path.lastIndexOf('/'));
- }
- return rc;
-}
-
-int main(int argc, char **argv)
-{
- QCoreApplication app(argc, argv);
- printf("Version %s, SHA1 %s\n", GIT_VERSION, GIT_HASH);
-
- mount(QString(), "/", "remount,rw");
- execute("mkdir", QStringList() << "-p" << "/mnt/boot");
- execute("mkdir", QStringList() << "-p" << "/mnt/root");
- execute("mkdir", QStringList() << "-p" << UPDATE_MOUNTPOINT);
- mount("/dev/mmcblk0p1", "/mnt/boot", "ro");
-
- QByteArray update_state = readAll("/mnt/boot/update/state").trimmed();
- if (update_state.isEmpty())
- qFatal("Update state is empty");
-
- if (update_state == "v")
- qFatal("Update state is 'valid', this should not happen");
- else if (update_state == "t")
- qDebug() << "Update state is 'testing', this should not happen";
- else if (update_state == "u")
- qDebug() << "Update state is 'update'";
- else
- qDebug() << "Unknown update state:" << update_state;
-
- QStringList usbsticks = find_usb_storage();
-
- qDebug() << "Found USB storage devices:" << usbsticks;
-
- bool update_found = false;
- foreach (QString s, usbsticks) {
- if (QProcess::execute("mount", QStringList() << "-o" << "ro" << "/dev/" + s << UPDATE_MOUNTPOINT) == 0) {
- mounts << UPDATE_MOUNTPOINT;
- qDebug() << "mount successful";
-
- if (QFile::exists(UPDATE_MOUNTPOINT "/b2qt-update")) {
- qDebug() << "update found";
- update_found = true;
- break;
- }
- execute("umount", QStringList() << UPDATE_MOUNTPOINT);
- mounts.removeAt(mounts.lastIndexOf(UPDATE_MOUNTPOINT));
- qDebug() << "no update found";
- } else {
- qDebug() << "mount of" << s << "failed";
- }
- }
-
- Update update;
-
- if (update_found) {
- FileWrapper *fw = new FileWrapper(UPDATE_MOUNTPOINT "/b2qt-update", &update);
- if (!fw->open(QFile::ReadOnly))
- qFatal("Failed to open update");
- qDebug() << "Starting update from USB";
- update.setDevice(fw);
- } else {
- QByteArray update_source = readAll("/mnt/boot/update/source").trimmed();
- if (update_source.isEmpty()) {
- execute("umount", QStringList() << "/mnt/boot"); // FIXME
- mounts.removeAt(mounts.lastIndexOf("/mnt/boot"));
- qFatal("Update source is empty");
- }
-
- execute("udhcpc", QStringList() << "-i" << "eth0");
-
- QNetworkAccessManager *manager = new QNetworkAccessManager(0);
- QNetworkReply *reply = manager->get(QNetworkRequest(QUrl(update_source)));
- reply->setReadBufferSize(2000000); // 2 MB
-
- QObject::connect(reply, (void (QNetworkReply::*)(QNetworkReply::NetworkError))&QNetworkReply::error,
- [](QNetworkReply::NetworkError e){qDebug() << "network error" << e;});
- QObject::connect(reply, &QNetworkReply::sslErrors,
- [](QList<QSslError>){ qDebug() << "ssl errors";});
-
- qDebug() << "Starting update from Internet" << update_source;
- update.setDevice(reply);
- }
-
- app.exec();
-
- qDebug() << "unmount";
- cleanup();
-
- qDebug() << "sync";
- sync();
- qDebug() << "reboot; waiting 2 seconds";
- sleep(2);
- reboot(RB_AUTOBOOT);
- return 0;
-}
diff --git a/src/b2qt-update-application/tar.cpp b/src/b2qt-update-application/tar.cpp
deleted file mode 100644
index c0369ff..0000000
--- a/src/b2qt-update-application/tar.cpp
+++ /dev/null
@@ -1,309 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://qt.digia.com/
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://qt.digia.com/
-**
-****************************************************************************/
-
-#include "tar.h"
-#include <QProcess>
-#include <QDebug>
-#include <openssl/x509.h>
-#include <openssl/pem.h>
-
-static bool isZeroed(const char *ptr, unsigned int size)
-{
- while (size) {
- if (*ptr) {
- return false;
- }
- ++ptr;
- --size;
- }
- return true;
-}
-
-Tar::Tar(QIODevice *source)
- : QObject(source)
- , mSource(source)
- , mSize(0)
- , mRemainingSize(0)
- , mRemainingFileBytes(0)
- , mProcess(0)
- , mState(WaitForHeader)
- , x509(0)
- , mdctx(0)
-{
- // Initialize table with all digests in order to look them up by string later
- OpenSSL_add_all_digests();
-
- connect(source, &QIODevice::readyRead, this, &Tar::dataIncoming);
- connect(source, &QIODevice::aboutToClose, this, &Tar::aboutToClose);
-}
-
-Tar::~Tar()
-{
- if (x509)
- X509_free(x509);
- x509 = 0;
- if (mdctx)
- EVP_MD_CTX_destroy(mdctx);
- mdctx = 0;
-}
-
-const QByteArray &Tar::currentContent() const
-{
- return mContent;
-}
-
-unsigned long Tar::currentSize() const
-{
- return mSize;
-}
-
-QString Tar::currentFileName() const
-{
- if (mHeader.name[sizeof(mHeader.name)-1])
- return QString::fromLatin1(mHeader.name, sizeof(mHeader.name));
- else
- return QString::fromLatin1(mHeader.name);
-}
-
-void Tar::dataIncoming()
-{
- while (mSource->bytesAvailable() > 512) {
-
- if (mState == WaitForHeader) {
- if (mSource->bytesAvailable() < 512)
- return;
- if (mSource->read((char*)&mHeader, sizeof(mHeader)) != sizeof(mHeader))
- qFatal("Tar read error");
- if (isZeroed((char*)&mHeader, sizeof(mHeader))) {
- qDebug() << "Zero Tar block";
- qDebug() << "Bytes left" << mSource->bytesAvailable();
- mSource->close();
- return;
- }
- if (mHeader.name[0] == 0)
- qFatal("Header starts with 0");
-
- mSize = QString::fromLatin1(mHeader.size, sizeof(mHeader.size)-1).toULongLong(0, 8);
- mRemainingFileBytes = mSize;
- mRemainingSize = mSize;
- if (mSize % 512) // padding to 512 byte block
- mRemainingSize += 512 - (mSize % 512);
-
- if (mSize == 0) {
- qFatal("Size of file is 0");
- }
-
- mState = WaitForDecision;
- qDebug() << "Started file" << currentFileName() << mSize;
- if (x509)
- setupMDContext();
- emit startingFile(currentFileName());
- } else if (mState == WaitForDecision) {
- return;
- } else if (mState == Extract) {
- QByteArray ba;
-
- quint64 bytesToHandle = mRemainingSize;
-
- if (mSource->bytesAvailable() < mRemainingSize)
- bytesToHandle = mSource->bytesAvailable();
- if (bytesToHandle > 60000)
- bytesToHandle = 60000;
- ba = mSource->read(bytesToHandle);
-
- updateMDContext(ba);
- mProcess->write(ba);
- mProcess->waitForBytesWritten();
- mRemainingSize -= ba.size();
- // do not return
- } else if (mState == Receive) {
- QByteArray ba;
-
- if (mSource->bytesAvailable() > mRemainingSize)
- ba = mSource->read(mRemainingSize);
- else
- ba = mSource->readAll();
- updateMDContext(ba);
- mContent += ba;
- mRemainingSize -= ba.size();
- if (mContent.size() > mSize)
- mContent.resize(mSize);
- // do not return
- } else if (mState == Skip) {
- QByteArray ba;
-
- if (mSource->bytesAvailable() > mRemainingSize) {
- ba = mSource->read(mRemainingSize);
- } else {
- ba = mSource->readAll();
- }
- updateMDContext(ba);
- mRemainingSize -= ba.size();
- // drop data
- // do not return
- } else if (mState == WaitForContinue) {
- return;
- } else {
- qFatal("Unknown tar state");
- }
-
- if (mState != WaitForContinue && mState != WaitForHeader && mRemainingSize == 0) {
- if (mState == Extract) {
- qDebug() << "End tar process";
- // please tar
- // it needs 2 zeroed blocks
- char buffer[sizeof(mHeader)];
- memset(buffer, 0, sizeof(buffer));
- mProcess->write(buffer, sizeof(buffer));
- mProcess->write(buffer, sizeof(buffer));
- mProcess->waitForBytesWritten();
- mProcess->closeWriteChannel();
- mProcess->waitForFinished(-1);
- mProcess->deleteLater();
- mProcess = 0;
- }
- mState = WaitForContinue;
-
- emit(endingFile(currentFileName()));
- }
-
- }
-}
-
-void Tar::extractContent(const QString &targetDir)
-{
- if (mState == WaitForDecision) {
- qDebug() << Q_FUNC_INFO;
- mState = Extract;
- delete mProcess;
- mProcess = new QProcess(this);
- mProcess->setProcessChannelMode(QProcess::ForwardedChannels);
- mProcess->start("tar", QStringList() << "xvf" << "-" << "-C" << targetDir);
-
- // if we want to extract a file directly, the header needs to be passed to tar
- if (!currentFileName().endsWith(".tar"))
- mProcess->write((const char*)&mHeader, sizeof(mHeader));
- }
-}
-
-void Tar::receiveContent()
-{
- if (mState == WaitForDecision)
- mState = Receive;
-}
-
-void Tar::skipContent()
-{
- if (mState == WaitForDecision)
- mState = Skip;
-}
-
-void Tar::continueContent()
-{
- if (mState == WaitForContinue) {
- mState = WaitForHeader;
- mSize = 0;
- mContent.clear();
- delete mProcess;
- mProcess = 0;
- } else
- qDebug() << "Called" << Q_FUNC_INFO << "in wrong state";
-}
-
-void Tar::aboutToClose()
-{
- if (mState != WaitForHeader) {
- qWarning() << "unexpected close";
- }
- emit finished();
-}
-
-bool Tar::setVerificationData(const QString &certificateFileName, const QString &mdType)
-{
- if (x509)
- qFatal("Setting key twice");
-
- // Load key from file
- BIO *i = BIO_new(BIO_s_file());
- BIO *o = BIO_new_fp(stdout,BIO_NOCLOSE);
-
- if ((BIO_read_filename(i, certificateFileName.toLatin1().constData()) <= 0) ||
- ((x509 = PEM_read_bio_X509_AUX(i, NULL, NULL, NULL)) == NULL)) {
- qWarning() << "Invalid certificate, failed to read file" << certificateFileName;
- return false;
- }
- // Showing used certificate
- X509_print_ex(o, x509, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
- BIO_free(i);
- BIO_free(o);
- qDebug() << "Using verification key:" << certificateFileName;
-
- md = EVP_get_digestbyname(mdType.toLatin1().constData());
- if (md == NULL)
- qFatal("Digest not found");
- return true;
-}
-
-void Tar::setupMDContext()
-{
- if (mdctx)
- EVP_MD_CTX_destroy(mdctx);
- if (!(mdctx = EVP_MD_CTX_create()))
- qFatal("EVP_MD_CTX_create failed");
-
- EVP_PKEY *key = X509_get_pubkey(x509);
- if (key == NULL) {
- qFatal("X509_get_pubkey failed");
- }
-
- if (md == NULL)
- qFatal("No digest set");
-
- if (1 != EVP_DigestVerifyInit(mdctx, NULL, md, NULL, key))
- qFatal("EVP_DigestVerifyInit failed");
-}
-
-void Tar::updateMDContext(QByteArray data)
-{
- if (mRemainingFileBytes == 0)
- qFatal("Trying to update MD context when no more bytes are expected");
-
- if (mRemainingFileBytes < data.size())
- data = data.left(mRemainingFileBytes);
- mRemainingFileBytes -= data.size();
-
- if (!mdctx)
- return;
-
- if (1 != EVP_DigestVerifyUpdate(mdctx, data.constData(), data.size()))
- qFatal("EVP_DigestVerifyUpdate failed");
-}
-
-bool Tar::checkSignature(const QByteArray &signature)
-{
- return 1 == EVP_DigestVerifyFinal(mdctx, (unsigned char*)signature.constData(), signature.size());
-}
-
-bool Tar::verifyCurrentContent(const QByteArray &signature)
-{
- setupMDContext();
- if (1 != EVP_DigestVerifyUpdate(mdctx, mContent.constData(), mContent.size()))
- qFatal("EVP_DigestVerifyUpdate failed");
- return checkSignature(signature);
-}
diff --git a/src/b2qt-update-application/tar.h b/src/b2qt-update-application/tar.h
deleted file mode 100644
index e3ca1d2..0000000
--- a/src/b2qt-update-application/tar.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://qt.digia.com/
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://qt.digia.com/
-**
-****************************************************************************/
-
-#ifndef TAR_H
-#define TAR_H
-
-#include <QObject>
-#include <openssl/x509.h>
-class QIODevice;
-class QProcess;
-#define USTAR_HEADER_SIZE 512
-
-struct ustar_header
-{
-char name[100]; /* File name. Null-terminated if room. */
-char mode[8]; /* Permissions as octal string. */
-char uid[8]; /* User ID as octal string. */
-char gid[8]; /* Group ID as octal string. */
-char size[12]; /* File size in bytes as octal string. */
-char mtime[12]; /* Modification time in seconds from Jan 1, 1970, as octal string. */
-char chksum[8]; /* Sum of octets in header as octal string. */
-char typeflag; /* An enum ustar_type value. */
-char linkname[100]; /* Name of link target. Null-terminated if room. */
-char magic[6]; /* "ustar\0" */
-char version[2]; /* "00" */
-char uname[32]; /* User name, always null-terminated. */
-char gname[32]; /* Group name, always null-terminated. */
-char devmajor[8]; /* Device major number as octal string. */
-char devminor[8]; /* Device minor number as octal string. */
-char prefix[155]; /* Prefix to file name. Null-terminated if room. */
-char padding[12]; /* Pad to 512 bytes. */
-} __attribute__((packed));
-
-class Tar : public QObject
-{
- Q_OBJECT
-
-public:
- Tar(QIODevice *source);
- virtual ~Tar();
-
- const QByteArray &currentContent() const;
- unsigned long currentSize() const;
- QString currentFileName() const;
-
- enum State { WaitForHeader, WaitForDecision, Extract, Receive, Skip, WaitForContinue};
- bool setVerificationData(const QString &certificateFileName, const QString &md);
- bool checkSignature(const QByteArray &signature);
- bool verifyCurrentContent(const QByteArray &signature);
-
-signals:
- void startingFile(const QString &name);
- void endingFile(const QString &name);
- void finished();
-
-public slots:
- void extractContent(const QString &targetDir);
- void receiveContent();
- void skipContent();
- void dataIncoming();
- void continueContent();
-
-private slots:
- void aboutToClose();
-
-private:
- void setupMDContext();
- void updateMDContext(QByteArray);
-
- QIODevice *mSource;
- qint64 mSize;
- qint64 mRemainingSize; // File Size + Padding
- qint64 mRemainingFileBytes; // File Size without Padding
- ustar_header mHeader;
- QByteArray mContent;
- QProcess *mProcess;
- State mState;
- X509 *x509;
- EVP_MD_CTX *mdctx;
- const EVP_MD *md;
-};
-
-#endif // TAR_H
diff --git a/src/b2qt-update-application/update.cpp b/src/b2qt-update-application/update.cpp
deleted file mode 100644
index 79fea64..0000000
--- a/src/b2qt-update-application/update.cpp
+++ /dev/null
@@ -1,202 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://qt.digia.com/
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://qt.digia.com/
-**
-****************************************************************************/
-
-#include "update.h"
-#include "tar.h"
-#include <QDebug>
-#include <QCoreApplication>
-#include <QProcess>
-#include <QFile>
-
-extern QStringList mounts;
-bool writeAll(const QString &fileName, const QByteArray &content);
-static QStringList allowedFiles;
-QByteArray readAll(const QString &fileName);
-bool execute(const QString &binary, const QStringList &arguments);
-bool mount(const QString &device, const QString &mountpoint, const QString &arguments = QString());
-
-QMap<QString,QString> parseMetaInfo(const QByteArray &data)
-{
- QMap<QString,QString> rc;
- QList<QByteArray> list = data.split('\n');
- foreach (const QByteArray &ba, list) {
- if (ba.isEmpty())
- continue;
- int i = ba.indexOf(':');
- if (i < 0 || i == ba.size())
- qFatal("Invalid meta.info content: No colon found or no data after colon");
-
- QString key = ba.left(i);
- QString value = ba.mid(i+1).trimmed();
-
- if (rc.contains(key))
- qFatal("Invalid meta.info content: Same key given twice");
- rc.insert(key, value);
- }
- if (rc.isEmpty())
- qFatal("Invalid meta.info content: No keys given");
- return rc;
-}
-
-Update::Update(QObject *parent)
- : QObject(parent)
- , mTar(0)
- , mSource(0)
-{
- allowedFiles << "key.info" << "meta.info" << "keys.tar" << "uImage" << "rootfs.tar";
-}
-
-Update::~Update()
-{
-}
-
-//# openssl dgst -sha256 -sign priv.pem file.txt > file.txt.sig
-//# openssl dgst -sha256 -verify public.pem -signature file.txt.sig file.txt
-
-void Update::setDevice(QIODevice *source)
-{
- if (!source) {
- qFatal("Source device is NULL");
- return;
- }
-
- if (mSource) {
- qFatal("Source already set");
- return;
- }
-
- mSource = source;
- mTar = new Tar(mSource);
-
- connect(mTar, &Tar::startingFile, this, &Update::tarStartingFile);
- connect(mTar, &Tar::endingFile, this, &Update::tarEndingFile);
- connect(mTar, &Tar::finished, this, &Update::tarFinished);
-}
-
-void Update::tarStartingFile(const QString &name)
-{
- if (name == "key.info") {
- mTar->receiveContent();
- } else if (name.endsWith(".sig")) {
- mTar->receiveContent();
- mCurrentFile = name;
- mCurrentFile.chop(4);
-
- bool found = false;
- while (!allowedFiles.isEmpty()) {
- QString n = allowedFiles.takeFirst();
- if (n == mCurrentFile) {
- found = true;
- break;
- }
- }
-
- if (!found)
- qFatal("File not allowed");
-
- } else if (mCurrentFile != name) {
- qFatal("Invalid file order");
- } else {
- if (mCurrentFile == "meta.info") {
- mTar->receiveContent();
- } else if (mCurrentFile == "uImage") {
- mount(QString(), "/mnt/boot", "remount,rw");
- mTar->extractContent("/mnt/boot");
- } else if (mCurrentFile == "rootfs.tar") {
- qDebug() << "Formatting rootfs";
- execute("mkfs." + mMetaInfo["filesystemType"], QStringList() << mMetaInfo["rootDevice"]);
- mount(mMetaInfo["rootDevice"], "/mnt/root");
- mTar->extractContent("/mnt/root");
- } else if (mCurrentFile == "keys.tar") {
- mount(QString(), "/mnt/boot", "remount,rw");
- execute("rm", QStringList() << "-r" << "/mnt/boot/update/keys/");
- execute("mkdir", QStringList() << "/mnt/boot/update/keys/");
- mTar->extractContent("/mnt/boot/update/keys");
- } else {
- qFatal("Unexpected file in update data");
- }
- }
-}
-
-void Update::tarEndingFile(const QString &name)
-{
- if (name == "meta.info") {
- QMap<QString,QString> map = parseMetaInfo(mTar->currentContent());
-
- // Some rough sanity checks
- if (!map.contains("version"))
- qFatal("No version information found" );
- if (map["version"] != "1")
- qFatal("Invalid update version");
- if (!map.contains("platform") || map["platform"].isEmpty())
- qFatal("Platform information missing");
- if (map["platform"] != readAll("/mnt/boot/update/platform").trimmed())
- qFatal("Invalid platform information");
- else
- qDebug() << "Platform matches";
- if (!map.contains("rootDevice") || map["rootDevice"].isEmpty())
- qFatal("Root device information missing");
- if (!QFile::exists(map["rootDevice"]))
- qFatal("Root device not found");
- if (!map.contains("key") || map["key"].isEmpty() || map["key"].contains('/'))
- qFatal("Invalid or no key fingerprint");
- if (!map.contains("digest") || map["digest"].isEmpty())
- qFatal("Invalid digest type");
- if (!map.contains("filesystemType") || map["filesystemType"].isEmpty() || map["filesystemType"].contains(' ') || map["filesystemType"].contains('/'))
- qFatal("Invalid filesystem type");
-
- mMetaInfo = map;
-
- if (!mTar->setVerificationData("/mnt/boot/update/keys/" + mMetaInfo["key"], mMetaInfo["digest"]))
- qFatal("Loading of certificate failed");
-
- // Now verify the meta.info itself
- if (mTar->verifyCurrentContent(mCurrentSignature)) {
- qDebug() << "meta.info VERIFIED OK";
- } else {
- qDebug() << "meta.info VERIFICATION FAILED";
- qFatal("VERIFICATION FAILED");
- return;
- }
-
- } else if (name.endsWith(".sig")) {
- mCurrentSignature = mTar->currentContent();
- qDebug() << "Received signature with" << mCurrentSignature.size() << "bytes.";
- } else {
- if (mTar->checkSignature(mCurrentSignature)) {
- qDebug() << "VERIFIED OK";
- // FIXME: do something here
- } else {
- qDebug() << "VERIFICATION FAILED";
- qFatal("VERIFICATION FAILED");
- }
- }
-
- mTar->continueContent();
-}
-
-void Update::tarFinished()
-{
- qDebug() << "Update finished";
- mount(QString(), "/mnt/boot", "remount,rw");
- if (!writeAll("/mnt/boot/update/state", "t"))
- qFatal("Could not set state to testing");
- mount(QString(), "/mnt/boot", "remount,ro");
- qApp->exit();
-}
diff --git a/src/b2qt-update-application/update.h b/src/b2qt-update-application/update.h
deleted file mode 100644
index 830be56..0000000
--- a/src/b2qt-update-application/update.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://qt.digia.com/
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://qt.digia.com/
-**
-****************************************************************************/
-
-#ifndef UPDATE_H
-#define UPDATE_H
-
-#include <QObject>
-#include <QMap>
-class Tar;
-class QIODevice;
-
-class Update : public QObject
-{
- Q_OBJECT
-
-public:
- Update(QObject *parent = 0);
- virtual ~Update();
- void setDevice(QIODevice *source);
-
-private slots:
- void tarStartingFile(const QString &name);
- void tarEndingFile(const QString &name);
- void tarFinished();
-
-private:
- Tar *mTar;
- QIODevice *mSource;
- QString mCurrentFile;
- QByteArray mCurrentSignature;
- QMap<QString, QString> mMetaInfo;
-};
-
-#endif // UPDATE_H
diff --git a/src/b2qt-update-util/.gitignore b/src/b2qt-update-util/.gitignore
deleted file mode 100644
index 67f0098..0000000
--- a/src/b2qt-update-util/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-Makefile
-b2qt-update-util
-*.o
-moc_*.cpp
diff --git a/src/b2qt-update-util/b2qt-update-util.pro b/src/b2qt-update-util/b2qt-update-util.pro
deleted file mode 100644
index 0b5ab32..0000000
--- a/src/b2qt-update-util/b2qt-update-util.pro
+++ /dev/null
@@ -1,23 +0,0 @@
-QT = core
-SOURCES = main.cpp
-INSTALLS += target
-target.path = /usr/bin
-
-# Find out git hash
-unix:system(which git):HAS_GIT=TRUE
-win32:system(where git.exe):HAS_GIT=TRUE
-contains(HAS_GIT, TRUE) {
- GIT_HASH=$$system(git log -1 --format=%H)
- !system(git diff-index --quiet HEAD): GIT_HASH="$$GIT_HASH-dirty"
- GIT_VERSION=$$system(git describe --tags --exact-match)
- isEmpty(GIT_VERSION) : GIT_VERSION="unknown"
-} else {
- GIT_HASH="unknown"
- GIT_VERSION="unknown"
-}
-
-isEmpty(GIT_VERSION) : error("No suitable tag found")
-isEmpty(GIT_HASH) : error("No hash available")
-
-DEFINES+="GIT_HASH=\\\"$$GIT_HASH\\\""
-DEFINES+="GIT_VERSION=\\\"$$GIT_VERSION\\\""
diff --git a/src/b2qt-update-util/main.cpp b/src/b2qt-update-util/main.cpp
deleted file mode 100644
index 137cbd5..0000000
--- a/src/b2qt-update-util/main.cpp
+++ /dev/null
@@ -1,144 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://qt.digia.com/
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://qt.digia.com/
-**
-****************************************************************************/
-
-#include <QCoreApplication>
-#include <sys/reboot.h>
-#include <QFile>
-#include <QDebug>
-#include <unistd.h>
-#include <QStringList>
-#include <QProcess>
-
-bool mount_boot()
-{
- // In some cases the boot partition is already mounted somewhere else.
- // Mounting it again is no problem but data loss will happen.
- QProcess::execute("umount", QStringList() << "/dev/mmcblk0p1"); // Ignore return value
- return QProcess::execute("mount", QStringList() << "/dev/mmcblk0p1" << "/boot") == 0;
-}
-
-bool umount_boot()
-{
- return QProcess::execute("umount", QStringList() << "/boot") == 0;
-}
-
-bool finish_update()
-{
- if (!mount_boot()) {
- qWarning() << "Could not mount /boot";
- return false;
- }
- QFile f("/boot/update/state");
- if (!f.open(QFile::WriteOnly)) {
- qWarning() << "Could not open file for writing";
- return false;
- }
- if (f.write("v") != 1) {
- qWarning() << "Write error";
- return false;
- }
- fsync(f.handle());
- f.close();
- if (!umount_boot()) {
- qWarning() << "Could not unmount /boot";
- return false;
- }
- return true;
-}
-
-int start_update(const QString &source)
-{
- if (!mount_boot()) {
- qWarning() << "Could not mount /boot";
- return false;
- }
- {
- QFile f("/boot/update/source");
- if (!f.open(QFile::WriteOnly)) {
- qWarning() << "Could not open file for writing";
- return false;
- }
- QByteArray ba = source.toUtf8();
-
- if (f.write(ba) != ba.size()) {
- qWarning() << "Write error";
- return false;
- }
- fsync(f.handle());
- f.close();
- }
-
- {
- QFile f("/boot/update/state");
- if (!f.open(QFile::WriteOnly)) {
- qWarning() << "Could not open file for writing";
- return false;
- }
- if (f.write("u") != 1) {
- qWarning() << "Write error";
- return false;
- }
- fsync(f.handle());
- f.close();
- }
- if (!umount_boot()) {
- qWarning() << "Could not unmount /boot";
- return false;
- }
- reboot(RB_AUTOBOOT);
- return true;
-}
-
-void usage()
-{
- fprintf(stderr,
- "b2qt-update [start|finish] [...]\n"
- " start: For internet update provide a http URL as parameter\n"
- " finish: An update\n"
- );
-}
-
-int main(int argc, char **argv)
-{
- QCoreApplication app(argc, argv);
- QStringList args = app.arguments();
-
- args.removeFirst();
- if (args.size() == 0) {
- usage();
- return 1;
- }
-
- QString arg = args.takeFirst();
-
- if (arg == "finish")
- return finish_update();
- else if (arg == "start") {
- if (args.size() == 0)
- return start_update(QString());
- else
- return start_update(args.takeFirst());
- } else if (arg == "version") {
- printf("Version %s, SHA1 %s\n", GIT_VERSION, GIT_HASH);
- return 0;
- } else {
- usage();
- return 1;
- }
-}
diff --git a/src/doc/config/b2qt-project.qdocconf b/src/doc/config/b2qt-project.qdocconf
index c7b48fd..753340b 100644
--- a/src/doc/config/b2qt-project.qdocconf
+++ b/src/doc/config/b2qt-project.qdocconf
@@ -1,6 +1,6 @@
project = QtForDeviceCreation
-description = Qt 5.5 for Device Creation
-version = 5.5.1
+description = Qt 5.6 for Device Creation
+version = 5.6.0
sourcedirs += ../src \
../../imports/wifi \
@@ -9,11 +9,13 @@ sourcedirs += ../src \
headerdirs += ../../wifi
-exampledirs += ../../../examples
+exampledirs += ../../../examples
imagedirs += ../images
indexes = $QT_INSTALL_DOCS/qtquick/qtquick.index \
+ $QT_INSTALL_DOCS/qtqml/qtqml.index \
+ $QT_INSTALL_DOCS/qtdoc/qtdoc.index \
$QT_INSTALL_DOCS/qtgui/qtgui.index \
$QT_INSTALL_DOCS/qtcore/qtcore.index \
$QT_INSTALL_DOCS/qtserialport/qtserialport.index \
@@ -21,17 +23,20 @@ indexes = $QT_INSTALL_DOCS/qtquick/qtquick.index \
$QT_INSTALL_DOCS/qtwebengine/qtwebengine.index \
$QT_INSTALL_DOCS/qtquickcontrols/qtquickcontrols.index
+# Listing qmake.index as part of 'indexes' fails, add a dependency as workaround
+depends = qmake
+
qhp.projects = B2Qt
qhp.B2Qt.file = b2qt.qhp
-qhp.B2Qt.namespace = com.digia.b2qt.551
+qhp.B2Qt.namespace = com.digia.b2qt.560
qhp.B2Qt.virtualFolder = b2qt
-qhp.B2Qt.indexTitle = Qt 5.5 for Device Creation
+qhp.B2Qt.indexTitle = Qt 5.6 for Device Creation
qhp.B2Qt.indexRoot =
qhp.B2Qt.subprojects = manual
-qhp.B2Qt.subprojects.manual.title = Qt 5.5 for Device Creation
-qhp.B2Qt.subprojects.manual.indexTitle = Qt 5.5 for Device Creation
+qhp.B2Qt.subprojects.manual.title = Qt 5.6 for Device Creation
+qhp.B2Qt.subprojects.manual.indexTitle = Qt 5.6 for Device Creation
qhp.B2Qt.subprojects.manual.type = manual
macro.B2Q = "Boot to Qt"
@@ -39,7 +44,7 @@ macro.SDK = "Qt for Device Creation"
macro.B2QA = "\\e {Boot to Qt for embedded Android}"
macro.B2QL = "\\e {Boot to Qt for embedded Linux}"
-navigation.landingpage = "Qt 5.5 for Device Creation"
+navigation.landingpage = "Qt 5.6 for Device Creation"
navigation.qmltypespage = "Add-On Modules"
Cpp.ignoredirectives += Q_DECLARE_LOGGING_CATEGORY
diff --git a/src/doc/src/devices/qtee-architech-tibidabo.qdoc b/src/doc/src/devices/qtee-architech-tibidabo.qdoc
index 87d070a..4663195 100644
--- a/src/doc/src/devices/qtee-architech-tibidabo.qdoc
+++ b/src/doc/src/devices/qtee-architech-tibidabo.qdoc
@@ -17,7 +17,7 @@
**
****************************************************************************/
/*!
- \target ArchiTech Tibidabo (embedded Linux)
+ \keyword ArchiTech Tibidabo
\page qtee-preparing-hardware-tibidabo.html
\title Preparing ArchiTech Tibidabo
\previouspage qtee-installation-guide.html
@@ -49,7 +49,7 @@
\badcode
cd <INSTALL_DIR>
- sudo 5.5/Boot2Qt/tibidabo-eLinux/images/deploy.sh /dev/<device_name>
+ sudo dd bs=4k if=5.6/Boot2Qt/tibidabo/images/b2qt-embedded-qt5-image-tibidabo.img of=/dev/<device_name>
\endcode
After the installation is complete, insert the SD card, power on the device and check that
diff --git a/src/doc/src/devices/qtee-bd-sl-imx6.qdoc b/src/doc/src/devices/qtee-bd-sl-imx6.qdoc
index 28adf93..e6c90f8 100644
--- a/src/doc/src/devices/qtee-bd-sl-imx6.qdoc
+++ b/src/doc/src/devices/qtee-bd-sl-imx6.qdoc
@@ -67,7 +67,7 @@
\badcode
cd <INSTALL_DIR>
- sudo 5.5/Boot2Qt/nitrogen6x-eLinux/images/deploy.sh /dev/<device_name>
+ sudo dd bs=4k if=5.6/Boot2Qt/nitrogen6x/images/b2qt-embedded-qt5-image-nitrogen6x.img of=/dev/<device_name>
\endcode
After the installation is complete, insert the SD card, power on the device and check that
diff --git a/src/doc/src/devices/qtee-beaglebone-black.qdoc b/src/doc/src/devices/qtee-beaglebone-black.qdoc
index dc9dce9..e3a1469 100644
--- a/src/doc/src/devices/qtee-beaglebone-black.qdoc
+++ b/src/doc/src/devices/qtee-beaglebone-black.qdoc
@@ -17,7 +17,7 @@
**
****************************************************************************/
/*!
- \target BeagleBone Black (embedded Linux)
+ \keyword BeagleBone Black
\page qtee-preparing-hardware-beaglebone.html
\title Preparing BeagleBone Black
\previouspage qtee-installation-guide.html
@@ -49,7 +49,7 @@
\badcode
cd <INSTALL_DIR>
- sudo 5.5/Boot2Qt/beaglebone-eLinux/images/deploy.sh /dev/<device_name>
+ sudo dd bs=4k if=5.6/Boot2Qt/beaglebone/images/b2qt-embedded-qt5-image-beaglebone.img of=/dev/<device_name>
\endcode
After the installation is complete, insert the SD card, power on the device and check that
diff --git a/src/doc/src/devices/qtee-imx53.qdoc b/src/doc/src/devices/qtee-imx53.qdoc
index d732656..a6108cf 100644
--- a/src/doc/src/devices/qtee-imx53.qdoc
+++ b/src/doc/src/devices/qtee-imx53.qdoc
@@ -17,7 +17,7 @@
**
****************************************************************************/
/*!
- \target i.MX53 Quick Start Board (embedded Linux)
+ \keyword i.MX53 Quick Start Board
\page qtee-preparing-hardware-imx53qsb.html
\title Preparing i.MX53 Quick Start Board
\previouspage qtee-installation-guide.html
diff --git a/src/doc/src/devices/qtee-kontron-smarc-samx6i.qdoc b/src/doc/src/devices/qtee-kontron-smarc-samx6i.qdoc
index 670ce51..a0f2549 100644
--- a/src/doc/src/devices/qtee-kontron-smarc-samx6i.qdoc
+++ b/src/doc/src/devices/qtee-kontron-smarc-samx6i.qdoc
@@ -17,7 +17,7 @@
**
****************************************************************************/
/*!
- \target Kontron SMARC-sAMX6i (embedded Linux)
+ \keyword Kontron SMARC-sAMX6i
\page qtee-preparing-hardware-smarc-samx6i.html
\title Preparing Kontron SMARC-sAMX6i
\previouspage qtee-installation-guide.html
diff --git a/src/doc/src/devices/qtee-raspberry-pi.qdoc b/src/doc/src/devices/qtee-raspberry-pi.qdoc
index 4340065..9e58089 100644
--- a/src/doc/src/devices/qtee-raspberry-pi.qdoc
+++ b/src/doc/src/devices/qtee-raspberry-pi.qdoc
@@ -17,7 +17,7 @@
**
****************************************************************************/
/*!
- \target Raspberry Pi 2 Model B (embedded Linux)
+ \keyword Raspberry Pi 2 Model B
\page qtee-preparing-hardware-rasberrypi.html
\title Preparing Raspberry Pi 2
\previouspage qtee-installation-guide.html
@@ -51,7 +51,7 @@
\badcode
cd <INSTALL_DIR>
- sudo 5.5/Boot2Qt/raspberrypi2-eLinux/images/deploy.sh /dev/<device_name>
+ sudo dd bs=4k if=5.6/Boot2Qt/raspberrypi2/images/b2qt-embedded-qt5-image-raspberrypi2.img of=/dev/<device_name>
\endcode
After the image has been deployed, insert the SD card, power on the device and check that
diff --git a/src/doc/src/devices/qtee-sabre-sd-imx6.qdoc b/src/doc/src/devices/qtee-sabre-sd-imx6.qdoc
index 819da9f..86f696f 100644
--- a/src/doc/src/devices/qtee-sabre-sd-imx6.qdoc
+++ b/src/doc/src/devices/qtee-sabre-sd-imx6.qdoc
@@ -17,19 +17,14 @@
**
****************************************************************************/
/*!
- \target SABRE SD i.MX6Quad (embedded Linux)
- \target SABRE SD i.MX6Dual (embedded Linux)
+ \keyword SABRE SD i.MX6Quad
\page qtee-preparing-hardware-imx6sabresd.html
- \title Preparing SABRE SD i.MX6
+ \title Preparing SABRE SD i.MX6Quad
\previouspage qtee-installation-guide.html
Take the following steps to prepare
\l {http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=RDIMX6SABREBRD}
- {Freescale SABRE SD i.MX6} boards for \B2Q:
- \list
- \li Freescale SABRE SD i.MX6Quad
- \li Freescale SABRE SD i.MX6Dual
- \endlist
+ {Freescale SABRE SD i.MX6Quad} for \B2Q:
\note It is important that you repeat the steps in this section after you
update \SDK.
@@ -52,19 +47,11 @@
\include detect-sd-card-device-name.qdocinc unmount
- To deploy the image on \b {i.MX6Quad}, enter the following commands:
+ To deploy the image, enter the following commands:
\badcode
cd <INSTALL_DIR>
- sudo 5.5/Boot2Qt/imx6qsabresd-eLinux/images/deploy.sh /dev/<device_name>
- \endcode
-
- To deploy the image on \b {i.MX6Dual}, you need to enter an additional boot
- argument:
-
- \badcode
- cd <INSTALL_DIR>
- sudo 5.5/Boot2Qt/imx6qsabresd-eLinux/images/deploy.sh --uboot u-boot-imx6dlsabresd.imx /dev/<device_name>
+ sudo dd bs=4k if=5.6/Boot2Qt/imx6qsabresd/images/b2qt-embedded-qt5-image-imx6qsabresd.img of=/dev/<device_name>
\endcode
After the image has been deployed, insert the SD card, power on the device and check that
diff --git a/src/doc/src/devices/qtee-supported-devices.qdoc b/src/doc/src/devices/qtee-supported-devices.qdoc
index 1c9f07d..360c940 100644
--- a/src/doc/src/devices/qtee-supported-devices.qdoc
+++ b/src/doc/src/devices/qtee-supported-devices.qdoc
@@ -29,15 +29,14 @@
\list
\li \l{Boundary Devices i.MX6 Boards}
- \li \l{SABRE SD i.MX6Quad (embedded Linux)}
- \li \l{SABRE SD i.MX6Dual (embedded Linux)}
- \li \l{Toradex Apalis iMX6 (embedded Linux)}
- \li \l{Toradex Colibri iMX6 (embedded Linux)}
- \li \l{Toradex Colibri VF50 and VF61 (embedded Linux)}
- \li \l{ArchiTech Tibidabo (embedded Linux)}
- \li \l{Kontron SMARC-sAMX6i (embedded Linux)}
- \li \l{BeagleBone Black (embedded Linux)}
- \li \l{Raspberry Pi 2 Model B (embedded Linux)}
+ \li \l{SABRE SD i.MX6Quad}
+ \li \l{Toradex Apalis iMX6}
+ \li \l{Toradex Colibri iMX6}
+ \li \l{Toradex Colibri VF50 and VF61}
+ \li \l{ArchiTech Tibidabo}
+ \li \l{Kontron SMARC-sAMX6i}
+ \li \l{BeagleBone Black}
+ \li \l{Raspberry Pi 2 Model B}
\endlist
If you use only the emulator, you can skip this step
@@ -99,28 +98,23 @@
the Qt online installer.
\table
- \header \li Devices with GPU \li eLinux
+ \header \li Devices with GPU
\row \li \l{http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=RDIMX6SABREBRD}
- {Freescale® SABRE SD i.MX6} (Freescale® i.MX6)\br
- ARM Cortex A9, Vivante GC2000 GPU, 1GB RAM
- \li \image ok
+ {Freescale® SABRE SD i.MX6Quad} (Freescale® i.MX6)\br
+ 4x ARM Cortex A9, Vivante GC2000 GPU, 1GB RAM
\row \li \l{http://beagleboard.org/products/beaglebone%20black}
{BeagleBone Black}\br
TIAM335x 1GHz ARM® Cortex-A8, 512 MB RAM
- \li \image ok
\row \li \b{\B2Q Emulator}\br
Included in the development environment
- \li \image ok
- \header \li Devices Without GPU \li
+ \header \li Devices Without GPU
\row \li \l{https://www.toradex.com/products/colibri-arm-computer-modules/freescale-vybrid-VF6xx-computer-module}
{Toradex Colibri VF61}\br
Dual-core (ARM Cortex-A5 + ARM Cortex-M4)\br
solution with 1 MB on-chip SRAM
- \li \image ok
\row \li \l{https://www.toradex.com/products/colibri-arm-computer-modules/freescale-vybrid-VF5xx-computer-module}
{Toradex Colibri VF50}\br
Single-core (ARM Cortex-A5) solution with 1.5 MB on-chip SRAM
- \li \image ok
\endtable
\section2 Group 2
@@ -139,38 +133,32 @@
online installer.
\table
- \header \li Devices with GPU \li eLinux
+ \header \li Devices with GPU
\row \li \l{http://boundarydevices.com/product-selector-guide/}
{Boundary Devices i.MX6 Boards}\br
Freescale® i.MX 6 based devices with\br
Vivante GC2000 GPU
- \li \image ok
\row \li \l{http://www.silica.com/product/architech-tibidabo.html}
{SILICA ArchiTech Tibidabo}\br
Freescale® i.MX 6Q ARM Cortex™-A9 @800 MHz,\br
2GB DDR3, 128MB NOR, Vivante GC2000 GPU
- \li \image ok
\row \li \l{http://www.toradex.com/products/apalis-arm-computer-modules/freescale-imx-6-computer-module}
{Toradex Apalis iMX6}\br
Freescale® i.MX 6Q ARM Cortex™-A9 @1 GHz,\br
1GB DDR3, 4GB eMMC, Vivante GC2000 GPU
- \li \image ok
\row \li \l{http://developer.toradex.com/product-selector/colibri-imx6}
{Toradex Colibri iMX6}\br
Freescale® i.MX6S or i.MX6DL ARM Cortex™-A9 @800MHz - 1GHz,\br
256MB (single core), 512MB (dual core) DDR3, 4GB eMMC,\br
Vivante 2D/3D GPU
- \li \image ok
\row \li \l{http://www.kontron.com/products/boards-and-standard-form-factors/smarc/smarc-samx6i.html}
{Kontron SMARC-sAMX6i}\br
Freescale® i.MX 6 ARM Cortex™-A9 @800MHz - 1.2GHz,\br
2GB DDR3, 2-64GB eMMC, Vivante GC2000 GPU
- \li \image ok
\row \li \l{https://www.raspberrypi.org/products/raspberry-pi-2-model-b/}
{Raspberry Pi 2 Model B}\br
900 Mhz ARM Cortexâ„¢-A7, Broadcom VideoCore IV\br
@250MHz GPU, 1GB LPDDR2 SDRAM
- \li \image ok
\endtable
\section2 Group 3
@@ -183,26 +171,25 @@
The Qt Company for consultancy services.
\table
- \header \li Device \li eLinux
+ \header \li Device
+ \row \li \l{http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=RDIMX6SABREBRD}
+ {Freescale® SABRE SD i.MX6Dual} (Freescale® i.MX6)\br
+ 2x ARM Cortex A9, Vivante GC2000 GPU, 1GB RAM
\row \li \l{http://beagleboard.org/hardware-xM}
{BeagleBoard-xM}\br
1GHz ARM Cortex A8, PowerVR SGX530 GPU,\br
512MB RAM
- \li \image ok
\row \li \l{http://processors.wiki.ti.com/index.php/AM335x_Starter_Kit}
{Sitara AM335x Starter Kit}\br
720 MHZ ARM Cortexâ„¢-A8 Starter Kit\br
with 4.3-inch LCD touchscreen
- \li \image ok
\row \li \l{http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=IMX53QSB}
{Freescale® iMX53 Quick Start Board}\br
1GHz ARM Cortexâ„¢-A8
- \li \image ok
\row \li \l{https://www.raspberrypi.org/products/model-b/}
{Raspberry Pi Model B}\br
700 Mhz ARM11, Broadcom VideoCore IV\br
@250MHz GPU, 512 MB (shared with GPU) RAM
- \li \image ok
\endtable
\section2 Supported Features on Reference Devices
diff --git a/src/doc/src/devices/qtee-toradex-apalis.qdoc b/src/doc/src/devices/qtee-toradex-apalis.qdoc
index 8d04b6e..b6acc6e 100644
--- a/src/doc/src/devices/qtee-toradex-apalis.qdoc
+++ b/src/doc/src/devices/qtee-toradex-apalis.qdoc
@@ -17,7 +17,7 @@
**
****************************************************************************/
/*!
- \target Toradex Apalis iMX6 (embedded Linux)
+ \keyword Toradex Apalis iMX6
\page qtee-preparing-hardware-apalis-imx6.html
\title Preparing Toradex Apalis iMX6
\previouspage qtee-installation-guide.html
@@ -51,7 +51,7 @@
\badcode
cd <INSTALL_DIR>
- sudo 5.5/Boot2Qt/apalis-imx6-eLinux/images/deploy.sh /dev/<device_name>
+ sudo dd bs=4k if=5.6/Boot2Qt/apalis-imx6/images/b2qt-embedded-qt5-image-apalis-imx6.img of=/dev/<device_name>
\endcode
By default, the Toradex Apalis iMX6 boots from its internal eMMC. In order to boot from
diff --git a/src/doc/src/devices/qtee-toradex-colibri-imx6.qdoc b/src/doc/src/devices/qtee-toradex-colibri-imx6.qdoc
index 475a05e..6b96c09 100644
--- a/src/doc/src/devices/qtee-toradex-colibri-imx6.qdoc
+++ b/src/doc/src/devices/qtee-toradex-colibri-imx6.qdoc
@@ -17,7 +17,7 @@
**
****************************************************************************/
/*!
- \target Toradex Colibri iMX6 (embedded Linux)
+ \keyword Toradex Colibri iMX6
\page qtee-preparing-hardware-colibri-imx6.html
\title Preparing Toradex Colibri iMX6
\previouspage qtee-installation-guide.html
@@ -51,7 +51,7 @@
\badcode
cd <INSTALL_DIR>
- sudo 5.5/Boot2Qt/colibri-imx6-eLinux/images/deploy.sh /dev/<device_name>
+ sudo dd bs=4k if=5.6/Boot2Qt/colibri-imx6/images/b2qt-embedded-qt5-image-colibri-imx6.img of=/dev/<device_name>
\endcode
By default, the Toradex Colibri iMX6 boots from its internal eMMC. In order to boot from
diff --git a/src/doc/src/devices/qtee-toradex-colibri-vf.qdoc b/src/doc/src/devices/qtee-toradex-colibri-vf.qdoc
index 7329fbf..fbf1f37 100644
--- a/src/doc/src/devices/qtee-toradex-colibri-vf.qdoc
+++ b/src/doc/src/devices/qtee-toradex-colibri-vf.qdoc
@@ -17,7 +17,7 @@
**
****************************************************************************/
/*!
- \target Toradex Colibri VF50 and VF61 (embedded Linux)
+ \keyword Toradex Colibri VF50 and VF61
\page qtee-preparing-hardware-colibri-vf.html
\title Preparing Toradex Colibri VF50 and VF61
\previouspage qtee-installation-guide.html
@@ -53,7 +53,7 @@
\badcode
cd <INSTALL_DIR>
- sudo 5.5/Boot2Qt/colibri-vf-eLinux/images/deploy.sh /dev/<device_name>
+ sudo dd bs=4k if=5.6/Boot2Qt/colibri-vf/images/b2qt-embedded-qt5-image-colibri-vf.img of=/dev/<device_name>
\endcode
By default, the Toradex Colibri VF devices boot from their internal NAND memory. In order to boot from
diff --git a/src/doc/src/qtee-changelog.qdoc b/src/doc/src/qtee-changelog.qdoc
index cfa0bd1..98358c7 100644
--- a/src/doc/src/qtee-changelog.qdoc
+++ b/src/doc/src/qtee-changelog.qdoc
@@ -291,7 +291,7 @@
currently not supported
\li \l {Qt Quick Compiler} (Technology Preview) was added to the \B2Q stack
\li Nexus 7 (2013) was added as a reference device for embedded Android
- \li \l{Preparing SABRE SD i.MX6}{Freescale SABRE SD i.MX6Quad} was
+ \li \l{Preparing SABRE SD i.MX6Quad}{Freescale SABRE SD i.MX6Quad} was
added as a reference device for embedded Linux
\li WiFi networking support and configuration were implemented on
embedded Linux
diff --git a/src/doc/src/qtee-custom-embedded-linux.qdoc b/src/doc/src/qtee-custom-embedded-linux.qdoc
index b6c77e6..5d2a577 100644
--- a/src/doc/src/qtee-custom-embedded-linux.qdoc
+++ b/src/doc/src/qtee-custom-embedded-linux.qdoc
@@ -20,7 +20,7 @@
\page qtee-custom-embedded-linux-image.html
\title Building Your Own Embedded Linux Image
\previouspage qtee-customization.html
- \nextpage qtee-changelog.html
+ \nextpage qtee-static-linking.html
\B2QL is built using the tools and resources from the \l {Yocto Project},
and is based on Yocto's reference distribution (\e Poky). You can
@@ -63,12 +63,12 @@
\section1 Setting Up Yocto Build Environment
- Run the setup script that initializes the Yocto environment. Using Raspberry Pi as
- an example:
+ Run the setup script that initializes the Yocto environment. Using Freescale
+ SABRE SD i.MX6Quad as an example:
\badcode
cd <BuildDir>
- <INSTALL_DIR>/5.5/Boot2Qt/sources/b2qt-yocto-meta/b2qt-init-build-env init --device raspberrypi
+ <INSTALL_DIR>/5.6/Boot2Qt/sources/b2qt-yocto-meta/b2qt-init-build-env init --device imx6qsabresd
\endcode
\c b2qt-init-build-env has the following additional command line options:
@@ -81,7 +81,7 @@
For all command line options, see:
\badcode
- <INSTALL_DIR>/5.5/Boot2Qt/sources/b2qt-yocto-meta/b2qt-init-build-env help
+ <INSTALL_DIR>/5.6/Boot2Qt/sources/b2qt-yocto-meta/b2qt-init-build-env help
\endcode
\note Support for Kontron SMARC-sAMX6i requires additional Yocto Board Support Package that is
@@ -90,11 +90,10 @@
\section1 Building the Image and Toolchain
After the Yocto environment is set up, you need to configure the
- build environment for your target device. Using Raspberry Pi as
- an example:
+ build environment for your target device:
\badcode
- export MACHINE=raspberrypi
+ export MACHINE=imx6qsabresd
source ./setup-environment.sh
\endcode
@@ -162,10 +161,10 @@
\e {Build scripts} source package contains scripts that can be used to
build Qt and all additional Qt addons that are part of \B2QL image.
To setup build environment for your target hardware, run the initialization
- script. Using Raspberry Pi as an example:
+ script. For example:
\badcode
- <INSTALL_DIR>/5.5/Boot2Qt/sources/b2qt-build-scripts/embedded-common/init_build_env.sh <INSTALL_DIR>/5.5/Boot2Qt/sources/b2qt-build-scripts/embedded-linux/config.raspberrypi
+ <INSTALL_DIR>/5.6/Boot2Qt/sources/b2qt-build-scripts/embedded-common/init_build_env.sh <INSTALL_DIR>/5.6/Boot2Qt/sources/b2qt-build-scripts/embedded-linux/config.imx6qsabresd
\endcode
\note You can use the same build directory for Qt and the Yocto image.
@@ -190,7 +189,7 @@
developing for your device. The following script does this for you.
\badcode
- <INSTALL_DIR>/5.5/Boot2Qt/sources/b2qt-build-scripts/embedded-common/setup_qtcreator.sh
+ <INSTALL_DIR>/5.6/Boot2Qt/sources/b2qt-build-scripts/embedded-common/setup_qtcreator.sh
\endcode
This will set up a new kit in Qt Creator, using the toolchain and Qt from
diff --git a/src/doc/src/qtee-customization.qdoc b/src/doc/src/qtee-customization.qdoc
index 272bc07..5604375 100644
--- a/src/doc/src/qtee-customization.qdoc
+++ b/src/doc/src/qtee-customization.qdoc
@@ -239,7 +239,7 @@
\section1 Using Network Connection for ADB
By default, \B2Q uses USB cable for communication between device and Qt Creator.
- On \B2QL, you can change the device to use ethernet network connection for the
+ On \B2QL, you can change the device to use ethernet network connection (IPv4) for the
communication. To enable network connection, you need to modify file
\c /etc/default/adbd located on the devices, and change value of \c USE_ETHERNET
to \c 'yes'. This can also be done with \c adb, while the device is still
diff --git a/src/doc/src/qtee-index.qdoc b/src/doc/src/qtee-index.qdoc
index 1439576..edec7bb 100644
--- a/src/doc/src/qtee-index.qdoc
+++ b/src/doc/src/qtee-index.qdoc
@@ -20,7 +20,7 @@
/*!
\page index.html
\nextpage qtee-overview.html
- \title Qt 5.5 for Device Creation
+ \title Qt 5.6 for Device Creation
\welcome
\e {Qt for Device Creation} is a commercial offering, providing a
@@ -45,15 +45,14 @@
\li \l{Preparing Hardware}
\list
\li \l{Boundary Devices i.MX6 Boards}
- \li \l{Preparing SABRE SD i.MX6}{SABRE SD i.MX6Quad (embedded Linux)}
- \li \l{Preparing SABRE SD i.MX6}{SABRE SD i.MX6Dual (embedded Linux)}
- \li \l{Preparing Toradex Apalis iMX6}{Toradex Apalis iMX6 (embedded Linux)}
- \li \l{Preparing Toradex Colibri iMX6}{Toradex Colibri iMX6 (embedded Linux)}
- \li \l{Preparing Toradex Colibri VF50 and VF61}{Toradex Colibri VF50 and VF61 (embedded Linux)}
- \li \l{Preparing ArchiTech Tibidabo}{ArchiTech Tibidabo (embedded Linux)}
- \li \l{Preparing Kontron SMARC-sAMX6i}{Kontron SMARC-sAMX6i (embedded Linux)}
- \li \l{Preparing BeagleBone Black}{BeagleBone Black (embedded Linux)}
- \li \l{Preparing Raspberry Pi 2}{Raspberry Pi 2 Model B (embedded Linux)}
+ \li \l{Preparing SABRE SD i.MX6Quad}{SABRE SD i.MX6Quad}
+ \li \l{Preparing Toradex Apalis iMX6}{Toradex Apalis iMX6}
+ \li \l{Preparing Toradex Colibri iMX6}{Toradex Colibri iMX6}
+ \li \l{Preparing Toradex Colibri VF50 and VF61}{Toradex Colibri VF50 and VF61}
+ \li \l{Preparing ArchiTech Tibidabo}{ArchiTech Tibidabo}
+ \li \l{Preparing Kontron SMARC-sAMX6i}{Kontron SMARC-sAMX6i}
+ \li \l{Preparing BeagleBone Black}{BeagleBone Black}
+ \li \l{Preparing Raspberry Pi 2}{Raspberry Pi 2 Model B}
\endlist
\li \l{Building and Running Embedded Applications}
\list
@@ -61,6 +60,9 @@
\endlist
\li \l{Customization}
\li \l{Building Your Own Embedded Linux Image}
+ \list
+ \li \l{Linking to Static Builds of Qt}
+ \endlist
\li \l{ChangeLog}
\li \l{Troubleshooting}
\li \l{Known Issues}
diff --git a/src/doc/src/qtee-static-linking.qdoc b/src/doc/src/qtee-static-linking.qdoc
new file mode 100644
index 0000000..33ebd6b
--- /dev/null
+++ b/src/doc/src/qtee-static-linking.qdoc
@@ -0,0 +1,226 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use the contact form at
+** http://www.qt.io
+**
+** This file is part of Qt Enterprise Embedded.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** the contact form at http://www.qt.io
+**
+****************************************************************************/
+/*!
+ \page qtee-static-linking.html
+ \title Linking to Static Builds of Qt
+ \previouspage qtee-custom-embedded-linux-image.html
+ \nextpage qtee-changelog.html
+
+ The device-specific sysroots in \B2Q come with a dynamically linked version
+ of Qt libraries (\c *.so files). In some cases, using static linking may be
+ preferable; it avoids the dependencies to external libraries, produces
+ single, self-contained application binaries making deployment easier,
+ and may lead to smaller binary size as unused code can be stripped away.
+
+ Internally, Qt uses dynamic linking with plugins for a lot of its functionality.
+ In order to have a fully functioning application, extra attention is needed on
+ which plugins to include in a static build. A downside of static linking is that
+ adding or updating a plugin requires a complete rebuild and redeployment of the
+ application.
+
+ \section1 Requirements
+
+ In addition to installing \SDK, ensure that required packages are installed for
+ all Qt modules that are included in the static build. For more information, see
+ \l {Qt for X11 Requirements#OpenGL Dependencies}{Qt for Linux Requirements} and
+ \l {Qt for Linux/X11#Requirements for Development Host}{Requirements for
+ Development Host}. Note that dependencies for the \e xcb platform plugin need
+ not be installed, as Qt will be configured without xcb support.
+
+ Install Qt sources by running the \e MaintenanceTool, located in the root of
+ \c INSTALL_DIR. Alternatively,
+ \l {https://wiki.qt.io/Building_Qt_5_from_Git#Getting_the_source_code}{clone}
+ the \e qt5 repository using git.
+
+ \section1 Building Qt for Static Linking
+
+ As the first step before configuring Qt, the \e mkspec for the target device
+ needs to be copied over to Qt sources, so that \e qmake will reference the
+ correct toolchains when creating the makefiles.
+
+ Using Raspberry Pi 2 as an example:
+
+ \badcode
+ cp -a <INSTALL_DIR>/5.6/Boot2Qt/raspberrypi2-eLinux/qt5/mkspecs/devices/linux-rasp-pi2-g++-b2qt \
+ <QT_SRC>/qtbase/mkspecs/devices
+ \endcode
+
+ Above, <QT_SRC> is the location of Qt sources (top-level directory containing
+ the \e configure script).
+
+ To use static linking, Qt must be built with the \c -static configuration
+ option. The following configure command selects the correct options and
+ \e sysroot for the Raspberry Pi 2.
+
+ To make the set of configure options reusable and more readable, the
+ device-specific paths are defined as environment variables:
+
+ \badcode
+ export SYSROOT_BASE=<INSTALL_DIR>/5.6/Boot2Qt/raspberrypi2-eLinux/toolchain/sysroots
+ export TARGET_DEVICE=linux-rasp-pi2-g++-b2qt
+ export SYSROOT_TARGET=cortexa7hf-vfp-vfpv4-neon-poky-linux-gnueabi
+ export CROSSCOMPILE_PREFIX=x86_64-pokysdk-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-
+ export HOST_PREFIX=~/build/qt5-rasp-pi2
+ \endcode
+
+ Description of the used variables:
+
+ \table
+ \row \li \c SYSROOT_BASE \li Base directory for the sysroots
+ (host and target) for the device
+
+ \row \li \c TARGET_DEVICE \li Target device (mkspec)
+
+ \row \li \c SYSROOT_TARGET \li Target sysroot directory under
+ \c SYSROOT_BASE
+
+ \row \li \c CROSSCOMPILE_PREFIX \li Cross-compilation toolchain path
+ and tool prefix (ends with '-')
+
+ \row \li \c HOST_PREFIX \li Location to install the host
+ binaries (qmake, moc, rcc, etc.)
+ \endtable
+
+ Using the above variables, \e configure can be called as follows:
+
+ \badcode
+ cd <QT_SRC>
+ ./configure -commercial -release -static \
+ -prefix /opt/qt5 -hostprefix $HOST_PREFIX \
+ -device $TARGET_DEVICE \
+ -device-option CROSS_COMPILE=$SYSROOT_BASE/$CROSSCOMPILE_PREFIX \
+ -sysroot $SYSROOT_BASE/$SYSROOT_TARGET \
+ -mysql_config $SYSROOT_BASE/$SYSROOT_TARGET/usr/bin/mysql_config \
+ -psql_config /dev/null \
+ -no-xcb -opengl es2 \
+ -nomake tests -nomake examples \
+ -skip qtwebengine
+ \endcode
+
+ Above, \c -prefix sets the intended destination of the Qt build on the
+ device (sysroot). Running \c {make install} will, by default, install Qt under
+ \c sysroot/prefix.
+
+ Compiling in \e xcb support is disabled, OpenGL ES 2.0 support is selected,
+ and \l [QtWebEngine] {Qt WebEngine} is excluded from the build.
+
+ More information about configure options is available in the \l [QtDoc]
+ {Qt for Embedded Linux#Configuring a Specific Device}{Qt for Embedded Linux}
+ documentation.
+
+ If configuration is successful, proceed to build and install Qt:
+
+ \badcode
+ make -j6 && make install
+ \endcode
+
+ The host tools (in particular, qmake) are now installed in \c HOST_PREFIX,
+ and the statically compiled Qt libraries are in
+ \c $SYSROOT_BASE/$SYSROOT_TARGET/opt/qt5. At this point, it's also possible
+ to add the new Qt version into Qt Creator and set up a \e Kit for it:
+
+ \list
+ \li \l {https://doc.qt.io/qtcreator/creator-project-qmake.html}{Qt Creator: Adding Qt Versions}
+ \li \l {https://doc.qt.io/qtcreator/creator-targets.html}{Qt Creator: Adding Kits}
+ \endlist
+
+ \section1 Building a Static Application
+
+ Building a stand-alone, static application requires all the necessary
+ plugins to be also statically linked. By default, qmake compiles a set of
+ plugins based on which Qt modules are used, and adds them to the \l
+ [QMake] {QTPLUGIN} variable.
+
+ After running qmake, the project directory contains a
+ \c <target_name>_plugin_import.cpp file that imports the plugins
+ using Q_IMPORT_PLUGIN() macros. The default set often contains more
+ plugins than are actually needed; to prevent unnecessary bloat, it's
+ possible to exclude certain plugin classes from the build.
+
+ For example, to exclude additional image format plugins, use:
+
+ \badcode
+ QTPLUGIN.imageformats = -
+ \endcode
+
+ Alternatively, the automatic generation of Q_IMPORT_PLUGIN() macros can
+ be turned off:
+
+ \badcode
+ CONFIG -= import_plugins
+ \endcode
+
+ The relevant plugins then need to be explicitly imported in the application
+ code.
+
+ For more information, see \l {How to Create Qt Plugins#Static Plugins}
+ {Static Plugins}.
+
+ \section2 Adding QML Imports
+
+ Similar to how Qt plugins are imported, qmake invokes the
+ \e qmlimportscanner tool to scan the application's .qml files, and
+ generates a \c <target_name>_qml_plugin_import.cpp file containing a
+ Q_IMPORT_PLUGIN() call for each static plugin associated with a QML import.
+
+ For example, for a simple QML application using the \c QtQuick and \c
+ QtQuick.Window import statements, the following statements are generated:
+
+ \code
+ Q_IMPORT_PLUGIN(QtQuick2Plugin)
+ Q_IMPORT_PLUGIN(QtQuick2WindowPlugin)
+ \endcode
+
+ In addition, the resources used by the QML imports need to be made
+ available to the QML engine. The best approach is to copy the files from
+ the source location into the application's project directory and add them
+ to the Qt resource system, together with the application's own resources.
+
+ At minimum, even though an import plugin uses no extra resources (.qml,
+ .js, or image files), its \e qmldir file needs to be accessible and
+ located under the correct \l [QtQml] {QML Import Path} {QML import path}.
+
+ For example, the following entries in a Qt resource collection file
+ (.qrc) places the qmldir files under the \c qml/ prefix in resources:
+
+ \badcode
+ <file>qml/QtQuick.2/qmldir</file>
+ <file>qml/QtQuick/Window.2/qmldir</file>
+ \endcode
+
+ Finally, the QML engine needs to be informed about the import path that's
+ now located within the resources. The following implementation of \c main()
+ sets the import path to \c qrc:/qml before loading \c main.qml:
+
+ \code
+ #include <QGuiApplication>
+ #include <QQmlApplicationEngine>
+
+ int main(int argc, char *argv[])
+ {
+ QGuiApplication app(argc, argv);
+
+ QQmlApplicationEngine engine;
+ engine.setImportPathList(QStringList(QStringLiteral("qrc:/qml")));
+ engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
+
+ return app.exec();
+ }
+ \endcode
+*/
diff --git a/src/doc/src/shared/b2qt-post-install-setup.qdocinc b/src/doc/src/shared/b2qt-post-install-setup.qdocinc
index e73b8e7..4444dfc 100644
--- a/src/doc/src/shared/b2qt-post-install-setup.qdocinc
+++ b/src/doc/src/shared/b2qt-post-install-setup.qdocinc
@@ -83,9 +83,9 @@
\list 1
\li Select \b{Tools > Options > Devices > Add}.
\li Select \b{Boot2Qt Device} > \b{Start Wizard}.
- \li Enter the device name and network address. You can check the device
- address in the \e{Launcher Settings} when the device is running the
- \B2Q demo.
+ \li Enter the device name and network address (IPv4). You can check the
+ device address in the \e{Launcher Settings} when the device is running
+ the \B2Q demo.
\li Select \b{Finish}.
\endlist
diff --git a/src/doppelganger/appops.cpp b/src/doppelganger/appops.cpp
deleted file mode 100644
index adeddcc..0000000
--- a/src/doppelganger/appops.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://qt.digia.com/
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://qt.digia.com/
-**
-****************************************************************************/
-
-#include "appops.h"
-
-#if Q_ANDROID_VERSION_MAJOR > 4 || (Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR >= 4)
-#include <binder/IServiceManager.h>
-#include <binder/IAppOpsCallback.h>
-
-class AppOpsPrivate : public android::BnAppOpsCallback
-{
-public:
- virtual void opChanged(int32_t, const android::String16&)
- {
-
- }
-
- virtual android::status_t onTransact(uint32_t,
- const android::Parcel&,
- android::Parcel*,
- uint32_t flags = 0)
- {
- (void)flags;
- return android::OK;
- }
-};
-#endif
-
-void AppOps::instantiate()
-{
-#if Q_ANDROID_VERSION_MAJOR > 4 || (Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR >= 4)
- android::defaultServiceManager()->addService(android::String16("appops"), new AppOpsPrivate);
-#endif
-}
diff --git a/src/doppelganger/appops.h b/src/doppelganger/appops.h
deleted file mode 100644
index 5e765a6..0000000
--- a/src/doppelganger/appops.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://qt.digia.com/
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://qt.digia.com/
-**
-****************************************************************************/
-
-#ifndef APPOPS_H
-#define APPOPS_H
-
-class AppOps
-{
-public:
- static void instantiate();
-};
-
-#endif // APPOPS_H
diff --git a/src/doppelganger/doppelganger.pro b/src/doppelganger/doppelganger.pro
deleted file mode 100644
index fa91169..0000000
--- a/src/doppelganger/doppelganger.pro
+++ /dev/null
@@ -1,22 +0,0 @@
-QT -= core gui
-
-TARGET = doppelganger
-
-LIBS += -lutils -lbinder -lcutils \
- -L$${ANDROID_PRODUCT_OUT}/obj/STATIC_LIBRARIES/libscheduling_policy_intermediates -lscheduling_policy -lpowermanager
-
-TEMPLATE = app
-
-SOURCES += main.cpp \
- permissioncontroller.cpp \
- schedulingpolicyservice.cpp \
- powermanager.cpp \
- appops.cpp
-
-HEADERS += \
- permissioncontroller.h \
- schedulingpolicyservice.h \
- powermanager.h \
- appops.h
-
-load(qt_tool)
diff --git a/src/doppelganger/main.cpp b/src/doppelganger/main.cpp
deleted file mode 100644
index 3e86a66..0000000
--- a/src/doppelganger/main.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include <binder/IPCThreadState.h>
-
-#include "permissioncontroller.h"
-#include "schedulingpolicyservice.h"
-#include "powermanager.h"
-#include "appops.h"
-
-using namespace android;
-
-int main(int, char *[])
-{
- sp<ProcessState> proc(ProcessState::self());
- SchedulingPolicyService::instantiate();
- PermissionController::instantiate();
- PowerManager::instantiate();
- AppOps::instantiate();
- IPCThreadState::self()->joinThreadPool();
-}
diff --git a/src/doppelganger/permissioncontroller.cpp b/src/doppelganger/permissioncontroller.cpp
deleted file mode 100644
index 9538b1a..0000000
--- a/src/doppelganger/permissioncontroller.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include "permissioncontroller.h"
-
-#include <binder/IServiceManager.h>
-
-using namespace android;
-
-PermissionController::PermissionController()
-{
-}
-
-void PermissionController::instantiate()
-{
- defaultServiceManager()->addService(String16("permission"), new PermissionController);
-}
-
-bool PermissionController::checkPermission(const String16 &, int32_t, int32_t)
-{
- // just bypass any permission
- return true;
-}
diff --git a/src/doppelganger/permissioncontroller.h b/src/doppelganger/permissioncontroller.h
deleted file mode 100644
index 211a346..0000000
--- a/src/doppelganger/permissioncontroller.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#ifndef PERMISSIONCONTROLLER_H
-#define PERMISSIONCONTROLLER_H
-
-#include <binder/IPermissionController.h>
-
-class PermissionController : public android::BnPermissionController
-{
-public:
- static void instantiate();
-
- bool checkPermission(const android::String16 &permission, int32_t pid, int32_t uid);
-
-private:
- PermissionController();
-};
-
-#endif // PERMISSIONCONTROLLER_H
diff --git a/src/doppelganger/powermanager.cpp b/src/doppelganger/powermanager.cpp
deleted file mode 100644
index 7f0da97..0000000
--- a/src/doppelganger/powermanager.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-
-#include "powermanager.h"
-
-#include <binder/IServiceManager.h>
-
-using namespace android;
-
-enum {
- ACQUIRE_WAKE_LOCK = IBinder::FIRST_CALL_TRANSACTION,
- ACQUIRE_WAKE_LOCK_UID = IBinder::FIRST_CALL_TRANSACTION + 1,
- RELEASE_WAKE_LOCK = IBinder::FIRST_CALL_TRANSACTION + 2,
- UPDATE_WAKE_LOCK_UIDS = IBinder::FIRST_CALL_TRANSACTION + 3,
-};
-
-void PowerManager::instantiate()
-{
- defaultServiceManager()->addService(String16("power"), new PowerManager());
-}
-
-status_t PowerManager::onTransact(uint32_t code,
- const Parcel &,
- Parcel *,
- uint32_t)
-{
- switch (code) {
- case ACQUIRE_WAKE_LOCK:
- case ACQUIRE_WAKE_LOCK_UID:
- case RELEASE_WAKE_LOCK:
- case UPDATE_WAKE_LOCK_UIDS:
- return NO_ERROR;
- default:
- break;
- }
-}
-
-#if Q_ANDROID_VERSION_MAJOR > 4 || (Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR >= 4)
-status_t PowerManager::acquireWakeLock(int,
- const sp<IBinder> &,
- const String16 &,
- const String16 &)
-{
- return OK;
-}
-
-status_t PowerManager::acquireWakeLockWithUid(int,
- const sp<IBinder> &,
- const String16 &,
- const String16 &,
- int)
-{
- return OK;
-}
-
-status_t PowerManager::updateWakeLockUids(const sp<IBinder> &,
- int,
- const int *)
-{
- return OK;
-}
-#else // < 4.4
-status_t PowerManager::acquireWakeLock(int, const sp<android::IBinder> &, const String16 &)
-{
- return OK;
-}
-#endif
-
-status_t PowerManager::releaseWakeLock(const sp<IBinder> &, int)
-{
- return OK;
-}
diff --git a/src/doppelganger/powermanager.h b/src/doppelganger/powermanager.h
deleted file mode 100644
index 23f2695..0000000
--- a/src/doppelganger/powermanager.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-
-#ifndef POWERMANAGER_H
-#define POWERMANAGER_H
-
-#include <powermanager/IPowerManager.h>
-
-namespace android {
-
-typedef BnInterface<IPowerManager> BnPowerManagerService;
-
-} // namespace android
-
-class PowerManager : public android::BnPowerManagerService
-{
-public:
- static void instantiate();
- android::status_t onTransact(uint32_t code,
- const android::Parcel &data,
- android::Parcel *reply,
- uint32_t flags);
-
-#if Q_ANDROID_VERSION_MAJOR > 4 || (Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR >= 4)
- virtual android::status_t acquireWakeLock(int flags,
- const android::sp<android::IBinder>& lock,
- const android::String16& tag,
- const android::String16& packageName);
- virtual android::status_t acquireWakeLockWithUid(int flags,
- const android::sp<android::IBinder>& lock,
- const android::String16& tag,
- const android::String16& packageName,
- int uid);
- virtual android::status_t updateWakeLockUids(const android::sp<android::IBinder>& lock,
- int len,
- const int *uids);
-#else // < 4.4
- virtual android::status_t acquireWakeLock(int flags,
- const android::sp<android::IBinder>& lock,
- const android::String16& tag);
-#endif
-
- virtual android::status_t releaseWakeLock(const android::sp<android::IBinder>& lock, int flags);
-};
-
-#endif // POWERMANAGER_H
diff --git a/src/doppelganger/schedulingpolicyservice.cpp b/src/doppelganger/schedulingpolicyservice.cpp
deleted file mode 100644
index 7113e6a..0000000
--- a/src/doppelganger/schedulingpolicyservice.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include "schedulingpolicyservice.h"
-
-#include <binder/IServiceManager.h>
-#include <binder/IPCThreadState.h>
-#include <cutils/sched_policy.h>
-#include <sched.h>
-
-using namespace android;
-
-enum {
- REQUEST_PRIORITY_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION
-};
-
-#define PRIORITY_MIN 1
-#define PRIORITY_MAX 3
-
-SchedulingPolicyService::SchedulingPolicyService()
-{
-}
-
-void SchedulingPolicyService::instantiate()
-{
- defaultServiceManager()->addService(String16("scheduling_policy"), new SchedulingPolicyService);
-}
-
-status_t SchedulingPolicyService::onTransact(uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags)
-{
- switch (code) {
- case REQUEST_PRIORITY_TRANSACTION: {
- CHECK_INTERFACE(ISchedulingPolicyService, data, reply);
- int32_t pid = data.readInt32();
- int32_t tid = data.readInt32();
- int32_t prio = data.readInt32();
- int res = requestPriority_helper(pid, tid, prio);
- reply->writeNoException();
- reply->writeInt32(res);
- return NO_ERROR;
- } break;
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-#if Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR < 3
-int SchedulingPolicyService::requestPriority(int32_t pid, int32_t tid, int32_t prio)
-#else
-int SchedulingPolicyService::requestPriority(int32_t pid, int32_t tid, int32_t prio, bool)
-#endif
-{
- return requestPriority_helper(pid, tid, prio);
-}
-
-int SchedulingPolicyService::requestPriority_helper(int32_t pid, int32_t tid, int32_t prio)
-{
- if (prio < PRIORITY_MIN || prio > PRIORITY_MAX)
- return PERMISSION_DENIED;
-
- int res = set_sched_policy(tid, IPCThreadState::self()->getCallingPid() == pid ? SP_AUDIO_SYS
- : SP_AUDIO_APP);
- if (res != NO_ERROR)
- return PERMISSION_DENIED;
-
- struct sched_param param;
- param.sched_priority = prio;
- res = sched_setscheduler(tid, SCHED_FIFO, &param);
- if (res)
- return PERMISSION_DENIED;
-
- return OK;
-}
diff --git a/src/doppelganger/schedulingpolicyservice.h b/src/doppelganger/schedulingpolicyservice.h
deleted file mode 100644
index 2dc1e42..0000000
--- a/src/doppelganger/schedulingpolicyservice.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#ifndef SCHEDULINGPOLICYSERVICE_H
-#define SCHEDULINGPOLICYSERVICE_H
-
-#include <frameworks/av/services/audioflinger/ISchedulingPolicyService.h>
-#include <binder/Parcel.h>
-
-class SchedulingPolicyService : public android::BnSchedulingPolicyService
-{
-public:
- static void instantiate();
-
- android::status_t onTransact(uint32_t code, const android::Parcel &data,
- android::Parcel *reply, uint32_t flags);
-
-#if Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR < 3
- int requestPriority(int32_t pid, int32_t tid, int32_t prio);
-#else
- int requestPriority(int32_t pid, int32_t tid, int32_t prio, bool);
-#endif
-
-private:
- SchedulingPolicyService();
- int requestPriority_helper(int32_t pid, int32_t tid, int32_t prio);
-};
-
-#endif // SCHEDULINGPOLICYSERVICE_H
diff --git a/src/imports/nativemedia/BufferQueue.cpp b/src/imports/nativemedia/BufferQueue.cpp
deleted file mode 100644
index 1dbd498..0000000
--- a/src/imports/nativemedia/BufferQueue.cpp
+++ /dev/null
@@ -1,1061 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#if Q_ANDROID_VERSION_MAJOR > 4 || (Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR >= 1)
-
-#define LOG_TAG "BufferQueue"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-//#define LOG_NDEBUG 0
-
-#define GL_GLEXT_PROTOTYPES
-#define EGL_EGLEXT_PROTOTYPES
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
-#include <gui/BufferQueue.h>
-#include <gui/ISurfaceComposer.h>
-#include <private/gui/ComposerService.h>
-
-#include <utils/Log.h>
-#include <gui/SurfaceTexture.h>
-#include <utils/Trace.h>
-
-// This compile option causes SurfaceTexture to return the buffer that is currently
-// attached to the GL texture from dequeueBuffer when no other buffers are
-// available. It requires the drivers (Gralloc, GL, OMX IL, and Camera) to do
-// implicit cross-process synchronization to prevent the buffer from being
-// written to before the buffer has (a) been detached from the GL texture and
-// (b) all GL reads from the buffer have completed.
-
-// During refactoring, do not support dequeuing the current buffer
-#undef ALLOW_DEQUEUE_CURRENT_BUFFER
-
-#ifdef ALLOW_DEQUEUE_CURRENT_BUFFER
-#define FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER true
-#warning "ALLOW_DEQUEUE_CURRENT_BUFFER enabled"
-#else
-#define FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER false
-#endif
-
-// Macros for including the BufferQueue name in log messages
-#define ST_LOGV(x, ...) ALOGV("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
-#define ST_LOGD(x, ...) ALOGD("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
-#define ST_LOGI(x, ...) ALOGI("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
-#define ST_LOGW(x, ...) ALOGW("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
-#define ST_LOGE(x, ...) ALOGE("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
-
-#define ATRACE_BUFFER_INDEX(index) \
- if (ATRACE_ENABLED()) { \
- char ___traceBuf[1024]; \
- snprintf(___traceBuf, 1024, "%s: %d", mConsumerName.string(), \
- (index)); \
- android::ScopedTrace ___bufTracer(ATRACE_TAG, ___traceBuf); \
- }
-
-namespace android {
-
-// Get an ID that's unique within this process.
-static int32_t createProcessUniqueId() {
- static volatile int32_t globalCounter = 0;
- return android_atomic_inc(&globalCounter);
-}
-
-static const char* scalingModeName(int scalingMode) {
- switch (scalingMode) {
- case NATIVE_WINDOW_SCALING_MODE_FREEZE: return "FREEZE";
- case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: return "SCALE_TO_WINDOW";
- case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: return "SCALE_CROP";
- default: return "Unknown";
- }
-}
-
-BufferQueue::BufferQueue( bool allowSynchronousMode, int bufferCount ) :
- mDefaultWidth(1),
- mDefaultHeight(1),
- mPixelFormat(PIXEL_FORMAT_RGBA_8888),
- mMinUndequeuedBuffers(bufferCount),
- mMinAsyncBufferSlots(bufferCount + 1),
- mMinSyncBufferSlots(bufferCount),
- mBufferCount(mMinAsyncBufferSlots),
- mClientBufferCount(0),
- mServerBufferCount(mMinAsyncBufferSlots),
- mSynchronousMode(false),
- mAllowSynchronousMode(allowSynchronousMode),
- mConnectedApi(NO_CONNECTED_API),
- mAbandoned(false),
- mFrameCounter(0),
- mBufferHasBeenQueued(false),
- mDefaultBufferFormat(0),
- mConsumerUsageBits(0),
- mTransformHint(0)
-{
- // Choose a name using the PID and a process-unique ID.
- mConsumerName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
-
- ST_LOGV("BufferQueue");
-#if 0
- sp<ISurfaceComposer> composer(ComposerService::getComposerService());
- mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
- if (mGraphicBufferAlloc == 0) {
- ST_LOGE("createGraphicBufferAlloc() failed in BufferQueue()");
- }
-#endif
-}
-
-BufferQueue::~BufferQueue() {
- ST_LOGV("~BufferQueue");
-}
-
-status_t BufferQueue::setBufferCountServerLocked(int bufferCount) {
- if (bufferCount > NUM_BUFFER_SLOTS)
- return BAD_VALUE;
-
- // special-case, nothing to do
- if (bufferCount == mBufferCount)
- return OK;
-
- if (!mClientBufferCount &&
- bufferCount >= mBufferCount) {
- // easy, we just have more buffers
- mBufferCount = bufferCount;
- mServerBufferCount = bufferCount;
- mDequeueCondition.broadcast();
- } else {
- // we're here because we're either
- // - reducing the number of available buffers
- // - or there is a client-buffer-count in effect
-
- // less than 2 buffers is never allowed
- if (bufferCount < 2)
- return BAD_VALUE;
-
- // when there is non client-buffer-count in effect, the client is not
- // allowed to dequeue more than one buffer at a time,
- // so the next time they dequeue a buffer, we know that they don't
- // own one. the actual resizing will happen during the next
- // dequeueBuffer.
-
- mServerBufferCount = bufferCount;
- mDequeueCondition.broadcast();
- }
- return OK;
-}
-
-bool BufferQueue::isSynchronousMode() const {
- Mutex::Autolock lock(mMutex);
- return mSynchronousMode;
-}
-
-void BufferQueue::setConsumerName(const String8& name) {
- Mutex::Autolock lock(mMutex);
- mConsumerName = name;
-}
-
-status_t BufferQueue::setDefaultBufferFormat(uint32_t defaultFormat) {
- Mutex::Autolock lock(mMutex);
- mDefaultBufferFormat = defaultFormat;
- return OK;
-}
-
-status_t BufferQueue::setConsumerUsageBits(uint32_t usage) {
- Mutex::Autolock lock(mMutex);
- mConsumerUsageBits = usage;
- return OK;
-}
-
-status_t BufferQueue::setTransformHint(uint32_t hint) {
- Mutex::Autolock lock(mMutex);
- mTransformHint = hint;
- return OK;
-}
-
-status_t BufferQueue::setBufferCount(int bufferCount) {
- ST_LOGV("setBufferCount: count=%d", bufferCount);
-
- sp<ConsumerListener> listener;
- {
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("setBufferCount: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
- if (bufferCount > NUM_BUFFER_SLOTS) {
- ST_LOGE("setBufferCount: bufferCount larger than slots available");
- return BAD_VALUE;
- }
-
- // Error out if the user has dequeued buffers
- for (int i=0 ; i<mBufferCount ; i++) {
- if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
- ST_LOGE("setBufferCount: client owns some buffers");
- return -EINVAL;
- }
- }
-
- const int minBufferSlots = mSynchronousMode ?
- mMinSyncBufferSlots : mMinAsyncBufferSlots;
- if (bufferCount == 0) {
- mClientBufferCount = 0;
- bufferCount = (mServerBufferCount >= minBufferSlots) ?
- mServerBufferCount : minBufferSlots;
- return setBufferCountServerLocked(bufferCount);
- }
-
- if (bufferCount < minBufferSlots) {
- ST_LOGE("setBufferCount: requested buffer count (%d) is less than "
- "minimum (%d)", bufferCount, minBufferSlots);
- return BAD_VALUE;
- }
-
- // here we're guaranteed that the client doesn't have dequeued buffers
- // and will release all of its buffer references.
- freeAllBuffersLocked();
- mBufferCount = bufferCount;
- mClientBufferCount = bufferCount;
- mBufferHasBeenQueued = false;
- mQueue.clear();
- mDequeueCondition.broadcast();
- listener = mConsumerListener;
- } // scope for lock
-
- if (listener != NULL) {
- listener->onBuffersReleased();
- }
-
- return OK;
-}
-
-int BufferQueue::query(int what, int* outValue)
-{
- ATRACE_CALL();
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("query: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
-
- int value;
- switch (what) {
- case NATIVE_WINDOW_WIDTH:
- value = mDefaultWidth;
- break;
- case NATIVE_WINDOW_HEIGHT:
- value = mDefaultHeight;
- break;
- case NATIVE_WINDOW_FORMAT:
- value = mPixelFormat;
- break;
- case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
- value = mSynchronousMode ?
- (mMinUndequeuedBuffers-1) : mMinUndequeuedBuffers;
- break;
- case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND:
- value = (mQueue.size() >= 2);
- break;
- default:
- return BAD_VALUE;
- }
- outValue[0] = value;
- return NO_ERROR;
-}
-
-status_t BufferQueue::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
- ATRACE_CALL();
- ST_LOGV("requestBuffer: slot=%d", slot);
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- ST_LOGE("requestBuffer: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
- if (slot < 0 || mBufferCount <= slot) {
- ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d",
- mBufferCount, slot);
- return BAD_VALUE;
- }
- mSlots[slot].mRequestBufferCalled = true;
- *buf = mSlots[slot].mGraphicBuffer;
- return NO_ERROR;
-}
-
-status_t BufferQueue::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
- uint32_t format, uint32_t usage) {
- ATRACE_CALL();
- ST_LOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage);
-
- if ((w && !h) || (!w && h)) {
- ST_LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
- return BAD_VALUE;
- }
-
- status_t returnFlags(OK);
- EGLDisplay dpy = EGL_NO_DISPLAY;
- EGLSyncKHR fence = EGL_NO_SYNC_KHR;
-
- { // Scope for the lock
- Mutex::Autolock lock(mMutex);
-
- if (format == 0) {
- format = mDefaultBufferFormat;
- }
- // turn on usage bits the consumer requested
- usage |= mConsumerUsageBits;
-
- int found = -1;
- int foundSync = -1;
- int dequeuedCount = 0;
- bool tryAgain = true;
- while (tryAgain) {
- if (mAbandoned) {
- ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
-
- // We need to wait for the FIFO to drain if the number of buffer
- // needs to change.
- //
- // The condition "number of buffers needs to change" is true if
- // - the client doesn't care about how many buffers there are
- // - AND the actual number of buffer is different from what was
- // set in the last setBufferCountServer()
- // - OR -
- // setBufferCountServer() was set to a value incompatible with
- // the synchronization mode (for instance because the sync mode
- // changed since)
- //
- // As long as this condition is true AND the FIFO is not empty, we
- // wait on mDequeueCondition.
-
- const int minBufferCountNeeded = mSynchronousMode ?
- mMinSyncBufferSlots : mMinAsyncBufferSlots;
-
- const bool numberOfBuffersNeedsToChange = !mClientBufferCount &&
- ((mServerBufferCount != mBufferCount) ||
- (mServerBufferCount < minBufferCountNeeded));
-
- if (!mQueue.isEmpty() && numberOfBuffersNeedsToChange) {
- // wait for the FIFO to drain
- mDequeueCondition.wait(mMutex);
- // NOTE: we continue here because we need to reevaluate our
- // whole state (eg: we could be abandoned or disconnected)
- continue;
- }
-
- if (numberOfBuffersNeedsToChange) {
- // here we're guaranteed that mQueue is empty
- freeAllBuffersLocked();
- mBufferCount = mServerBufferCount;
- if (mBufferCount < minBufferCountNeeded)
- mBufferCount = minBufferCountNeeded;
- mBufferHasBeenQueued = false;
- returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS;
- }
-
- // look for a free buffer to give to the client
- found = INVALID_BUFFER_SLOT;
- foundSync = INVALID_BUFFER_SLOT;
- dequeuedCount = 0;
- for (int i = 0; i < mBufferCount; i++) {
- const int state = mSlots[i].mBufferState;
- if (state == BufferSlot::DEQUEUED) {
- dequeuedCount++;
- }
-
- // this logic used to be if (FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER)
- // but dequeuing the current buffer is disabled.
- if (false) {
- // This functionality has been temporarily removed so
- // BufferQueue and SurfaceTexture can be refactored into
- // separate objects
- } else {
- if (state == BufferSlot::FREE) {
- /* We return the oldest of the free buffers to avoid
- * stalling the producer if possible. This is because
- * the consumer may still have pending reads of the
- * buffers in flight.
- */
- bool isOlder = mSlots[i].mFrameNumber <
- mSlots[found].mFrameNumber;
- if (found < 0 || isOlder) {
- foundSync = i;
- found = i;
- }
- }
- }
- }
-
- // clients are not allowed to dequeue more than one buffer
- // if they didn't set a buffer count.
- if (!mClientBufferCount && dequeuedCount) {
- ST_LOGE("dequeueBuffer: can't dequeue multiple buffers without "
- "setting the buffer count");
- return -EINVAL;
- }
-
- // See whether a buffer has been queued since the last
- // setBufferCount so we know whether to perform the
- // mMinUndequeuedBuffers check below.
- if (mBufferHasBeenQueued) {
- // make sure the client is not trying to dequeue more buffers
- // than allowed.
- const int avail = mBufferCount - (dequeuedCount+1);
- if (avail < (mMinUndequeuedBuffers-int(mSynchronousMode))) {
- ST_LOGE("dequeueBuffer: mMinUndequeuedBuffers=%d exceeded "
- "(dequeued=%d)",
- mMinUndequeuedBuffers-int(mSynchronousMode),
- dequeuedCount);
- return -EBUSY;
- }
- }
-
- // if no buffer is found, wait for a buffer to be released
- tryAgain = found == INVALID_BUFFER_SLOT;
- if (tryAgain) {
- mDequeueCondition.wait(mMutex);
- }
- }
-
-
- if (found == INVALID_BUFFER_SLOT) {
- // This should not happen.
- ST_LOGE("dequeueBuffer: no available buffer slots");
- return -EBUSY;
- }
-
- const int buf = found;
- *outBuf = found;
-
- ATRACE_BUFFER_INDEX(buf);
-
- const bool useDefaultSize = !w && !h;
- if (useDefaultSize) {
- // use the default size
- w = mDefaultWidth;
- h = mDefaultHeight;
- }
-
- const bool updateFormat = (format != 0);
- if (!updateFormat) {
- // keep the current (or default) format
- format = mPixelFormat;
- }
-
- // buffer is now in DEQUEUED (but can also be current at the same time,
- // if we're in synchronous mode)
- mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
-
- const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
- if ((buffer == NULL) ||
- (uint32_t(buffer->width) != w) ||
- (uint32_t(buffer->height) != h) ||
- (uint32_t(buffer->format) != format) ||
- ((uint32_t(buffer->usage) & usage) != usage))
- {
- status_t error;
- sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(w, h, format, usage);
- if (graphicBuffer == 0) {
- ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer "
- "failed");
- return error;
- }
- if (updateFormat) {
- mPixelFormat = format;
- }
-
- mSlots[buf].mAcquireCalled = false;
- mSlots[buf].mGraphicBuffer = graphicBuffer;
- mSlots[buf].mRequestBufferCalled = false;
- mSlots[buf].mFence = EGL_NO_SYNC_KHR;
- mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
-
- returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
- }
-
- dpy = mSlots[buf].mEglDisplay;
- fence = mSlots[buf].mFence;
- mSlots[buf].mFence = EGL_NO_SYNC_KHR;
- } // end lock scope
-
- if (fence != EGL_NO_SYNC_KHR) {
- EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
- // If something goes wrong, log the error, but return the buffer without
- // synchronizing access to it. It's too late at this point to abort the
- // dequeue operation.
- if (result == EGL_FALSE) {
- ST_LOGE("dequeueBuffer: error waiting for fence: %#x", eglGetError());
- } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
- ST_LOGE("dequeueBuffer: timeout waiting for fence");
- }
- eglDestroySyncKHR(dpy, fence);
- }
-
- ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", *outBuf,
- mSlots[*outBuf].mGraphicBuffer->handle, returnFlags);
-
- return returnFlags;
-}
-
-status_t BufferQueue::setSynchronousMode(bool enabled) {
- ATRACE_CALL();
- ST_LOGV("setSynchronousMode: enabled=%d", enabled);
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("setSynchronousMode: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
-
- status_t err = OK;
- if (!mAllowSynchronousMode && enabled)
- return err;
-
- if (!enabled) {
- // going to asynchronous mode, drain the queue
- err = drainQueueLocked();
- if (err != NO_ERROR)
- return err;
- }
-
- if (mSynchronousMode != enabled) {
- // - if we're going to asynchronous mode, the queue is guaranteed to be
- // empty here
- // - if the client set the number of buffers, we're guaranteed that
- // we have at least 3 (because we don't allow less)
- mSynchronousMode = enabled;
- mDequeueCondition.broadcast();
- }
- return err;
-}
-
-status_t BufferQueue::queueBuffer(int buf,
- const QueueBufferInput& input, QueueBufferOutput* output) {
- ATRACE_CALL();
- ATRACE_BUFFER_INDEX(buf);
-
- Rect crop;
- uint32_t transform;
- int scalingMode;
- int64_t timestamp;
-
- input.deflate(&timestamp, &crop, &scalingMode, &transform);
-
- ST_LOGV("queueBuffer: slot=%d time=%#llx crop=[%d,%d,%d,%d] tr=%#x "
- "scale=%s",
- buf, timestamp, crop.left, crop.top, crop.right, crop.bottom,
- transform, scalingModeName(scalingMode));
-
- sp<ConsumerListener> listener;
-
- { // scope for the lock
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- ST_LOGE("queueBuffer: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
- if (buf < 0 || buf >= mBufferCount) {
- ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d",
- mBufferCount, buf);
- return -EINVAL;
- } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
- ST_LOGE("queueBuffer: slot %d is not owned by the client "
- "(state=%d)", buf, mSlots[buf].mBufferState);
- return -EINVAL;
- } else if (!mSlots[buf].mRequestBufferCalled) {
- ST_LOGE("queueBuffer: slot %d was enqueued without requesting a "
- "buffer", buf);
- return -EINVAL;
- }
-
- const sp<GraphicBuffer>& graphicBuffer(mSlots[buf].mGraphicBuffer);
- Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
- Rect croppedCrop;
- crop.intersect(bufferRect, &croppedCrop);
- if (croppedCrop != crop) {
- ST_LOGE("queueBuffer: crop rect is not contained within the "
- "buffer in slot %d", buf);
- return -EINVAL;
- }
-
- if (mSynchronousMode) {
- // In synchronous mode we queue all buffers in a FIFO.
- mQueue.push_back(buf);
-
- // Synchronous mode always signals that an additional frame should
- // be consumed.
- listener = mConsumerListener;
- } else {
- // In asynchronous mode we only keep the most recent buffer.
- if (mQueue.empty()) {
- mQueue.push_back(buf);
-
- // Asynchronous mode only signals that a frame should be
- // consumed if no previous frame was pending. If a frame were
- // pending then the consumer would have already been notified.
- listener = mConsumerListener;
- } else {
- Fifo::iterator front(mQueue.begin());
- // buffer currently queued is freed
- mSlots[*front].mBufferState = BufferSlot::FREE;
- // and we record the new buffer index in the queued list
- *front = buf;
- }
- }
-
- mSlots[buf].mTimestamp = timestamp;
- mSlots[buf].mCrop = crop;
- mSlots[buf].mTransform = transform;
-
- switch (scalingMode) {
- case NATIVE_WINDOW_SCALING_MODE_FREEZE:
- case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
- case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
- break;
- default:
- ST_LOGE("unknown scaling mode: %d (ignoring)", scalingMode);
- scalingMode = mSlots[buf].mScalingMode;
- break;
- }
-
- mSlots[buf].mBufferState = BufferSlot::QUEUED;
- mSlots[buf].mScalingMode = scalingMode;
- mFrameCounter++;
- mSlots[buf].mFrameNumber = mFrameCounter;
-
- mBufferHasBeenQueued = true;
- mDequeueCondition.broadcast();
-
- output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint,
- mQueue.size());
-
- ATRACE_INT(mConsumerName.string(), mQueue.size());
- } // scope for the lock
-
- // call back without lock held
- if (listener != 0) {
- listener->onFrameAvailable();
- }
- return OK;
-}
-
-void BufferQueue::cancelBuffer(int buf) {
- ATRACE_CALL();
- ST_LOGV("cancelBuffer: slot=%d", buf);
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGW("cancelBuffer: BufferQueue has been abandoned!");
- return;
- }
-
- if (buf < 0 || buf >= mBufferCount) {
- ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
- mBufferCount, buf);
- return;
- } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
- ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
- buf, mSlots[buf].mBufferState);
- return;
- }
- mSlots[buf].mBufferState = BufferSlot::FREE;
- mSlots[buf].mFrameNumber = 0;
- mDequeueCondition.broadcast();
-}
-
-status_t BufferQueue::connect(int api, QueueBufferOutput* output) {
- ATRACE_CALL();
- ST_LOGV("connect: api=%d", api);
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("connect: BufferQueue has been abandoned!");
- return NO_INIT;
- }
-
- if (mConsumerListener == NULL) {
- ST_LOGE("connect: BufferQueue has no consumer!");
- return NO_INIT;
- }
-
- int err = NO_ERROR;
- switch (api) {
- case NATIVE_WINDOW_API_EGL:
- case NATIVE_WINDOW_API_CPU:
- case NATIVE_WINDOW_API_MEDIA:
- case NATIVE_WINDOW_API_CAMERA:
- if (mConnectedApi != NO_CONNECTED_API) {
- ST_LOGE("connect: already connected (cur=%d, req=%d)",
- mConnectedApi, api);
- err = -EINVAL;
- } else {
- mConnectedApi = api;
- output->inflate(mDefaultWidth, mDefaultHeight, mTransformHint,
- mQueue.size());
- }
- break;
- default:
- err = -EINVAL;
- break;
- }
-
- mBufferHasBeenQueued = false;
-
- return err;
-}
-
-status_t BufferQueue::disconnect(int api) {
- ATRACE_CALL();
- ST_LOGV("disconnect: api=%d", api);
-
- int err = NO_ERROR;
- sp<ConsumerListener> listener;
-
- { // Scope for the lock
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- // it is not really an error to disconnect after the surface
- // has been abandoned, it should just be a no-op.
- return NO_ERROR;
- }
-
- switch (api) {
- case NATIVE_WINDOW_API_EGL:
- case NATIVE_WINDOW_API_CPU:
- case NATIVE_WINDOW_API_MEDIA:
- case NATIVE_WINDOW_API_CAMERA:
- if (mConnectedApi == api) {
- drainQueueAndFreeBuffersLocked();
- mConnectedApi = NO_CONNECTED_API;
- mDequeueCondition.broadcast();
- listener = mConsumerListener;
- } else {
- ST_LOGE("disconnect: connected to another api (cur=%d, req=%d)",
- mConnectedApi, api);
- err = -EINVAL;
- }
- break;
- default:
- ST_LOGE("disconnect: unknown API %d", api);
- err = -EINVAL;
- break;
- }
- }
-
- if (listener != NULL) {
- listener->onBuffersReleased();
- }
-
- return err;
-}
-
-void BufferQueue::dump(String8& result) const
-{
- char buffer[1024];
- BufferQueue::dump(result, "", buffer, 1024);
-}
-
-void BufferQueue::dump(String8& result, const char* prefix,
- char* buffer, size_t SIZE) const
-{
- Mutex::Autolock _l(mMutex);
-
- String8 fifo;
- int fifoSize = 0;
- Fifo::const_iterator i(mQueue.begin());
- while (i != mQueue.end()) {
- snprintf(buffer, SIZE, "%02d ", *i++);
- fifoSize++;
- fifo.append(buffer);
- }
-
- snprintf(buffer, SIZE,
- "%s-BufferQueue mBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
- "mPixelFormat=%d, FIFO(%d)={%s}\n",
- prefix, mBufferCount, mSynchronousMode, mDefaultWidth,
- mDefaultHeight, mPixelFormat, fifoSize, fifo.string());
- result.append(buffer);
-
-
- struct {
- const char * operator()(int state) const {
- switch (state) {
- case BufferSlot::DEQUEUED: return "DEQUEUED";
- case BufferSlot::QUEUED: return "QUEUED";
- case BufferSlot::FREE: return "FREE";
- case BufferSlot::ACQUIRED: return "ACQUIRED";
- default: return "Unknown";
- }
- }
- } stateName;
-
- for (int i=0 ; i<mBufferCount ; i++) {
- const BufferSlot& slot(mSlots[i]);
- snprintf(buffer, SIZE,
- "%s%s[%02d] "
- "state=%-8s, crop=[%d,%d,%d,%d], "
- "xform=0x%02x, time=%#llx, scale=%s",
- prefix, (slot.mBufferState == BufferSlot::ACQUIRED)?">":" ", i,
- stateName(slot.mBufferState),
- slot.mCrop.left, slot.mCrop.top, slot.mCrop.right,
- slot.mCrop.bottom, slot.mTransform, slot.mTimestamp,
- scalingModeName(slot.mScalingMode)
- );
- result.append(buffer);
-
- const sp<GraphicBuffer>& buf(slot.mGraphicBuffer);
- if (buf != NULL) {
- snprintf(buffer, SIZE,
- ", %p [%4ux%4u:%4u,%3X]",
- buf->handle, buf->width, buf->height, buf->stride,
- buf->format);
- result.append(buffer);
- }
- result.append("\n");
- }
-}
-
-void BufferQueue::freeBufferLocked(int i) {
- mSlots[i].mGraphicBuffer = 0;
- if (mSlots[i].mBufferState == BufferSlot::ACQUIRED) {
- mSlots[i].mNeedsCleanupOnRelease = true;
- }
- mSlots[i].mBufferState = BufferSlot::FREE;
- mSlots[i].mFrameNumber = 0;
- mSlots[i].mAcquireCalled = false;
-
- // destroy fence as BufferQueue now takes ownership
- if (mSlots[i].mFence != EGL_NO_SYNC_KHR) {
- eglDestroySyncKHR(mSlots[i].mEglDisplay, mSlots[i].mFence);
- mSlots[i].mFence = EGL_NO_SYNC_KHR;
- }
-}
-
-void BufferQueue::freeAllBuffersLocked() {
- ALOGW_IF(!mQueue.isEmpty(),
- "freeAllBuffersLocked called but mQueue is not empty");
- mQueue.clear();
- mBufferHasBeenQueued = false;
- for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- freeBufferLocked(i);
- }
-}
-
-status_t BufferQueue::acquireBuffer(BufferItem *buffer) {
- ATRACE_CALL();
- Mutex::Autolock _l(mMutex);
- // check if queue is empty
- // In asynchronous mode the list is guaranteed to be one buffer
- // deep, while in synchronous mode we use the oldest buffer.
- if (!mQueue.empty()) {
- Fifo::iterator front(mQueue.begin());
- int buf = *front;
-
- ATRACE_BUFFER_INDEX(buf);
-
- if (mSlots[buf].mAcquireCalled) {
- buffer->mGraphicBuffer = NULL;
- } else {
- buffer->mGraphicBuffer = mSlots[buf].mGraphicBuffer;
- }
- buffer->mCrop = mSlots[buf].mCrop;
- buffer->mTransform = mSlots[buf].mTransform;
- buffer->mScalingMode = mSlots[buf].mScalingMode;
- buffer->mFrameNumber = mSlots[buf].mFrameNumber;
- buffer->mTimestamp = mSlots[buf].mTimestamp;
- buffer->mBuf = buf;
- mSlots[buf].mAcquireCalled = true;
-
- mSlots[buf].mBufferState = BufferSlot::ACQUIRED;
- mQueue.erase(front);
- mDequeueCondition.broadcast();
-
- ATRACE_INT(mConsumerName.string(), mQueue.size());
- } else {
- return NO_BUFFER_AVAILABLE;
- }
-
- return OK;
-}
-
-status_t BufferQueue::releaseBuffer(int buf, EGLDisplay display,
- EGLSyncKHR fence) {
- ATRACE_CALL();
- ATRACE_BUFFER_INDEX(buf);
-
- Mutex::Autolock _l(mMutex);
-
- if (buf == INVALID_BUFFER_SLOT) {
- return -EINVAL;
- }
-
- mSlots[buf].mEglDisplay = display;
- mSlots[buf].mFence = fence;
-
- // The buffer can now only be released if its in the acquired state
- if (mSlots[buf].mBufferState == BufferSlot::ACQUIRED) {
- mSlots[buf].mBufferState = BufferSlot::FREE;
- } else if (mSlots[buf].mNeedsCleanupOnRelease) {
- ST_LOGV("releasing a stale buf %d its state was %d", buf, mSlots[buf].mBufferState);
- mSlots[buf].mNeedsCleanupOnRelease = false;
- return STALE_BUFFER_SLOT;
- } else {
- ST_LOGE("attempted to release buf %d but its state was %d", buf, mSlots[buf].mBufferState);
- return -EINVAL;
- }
-
- mDequeueCondition.broadcast();
- return OK;
-}
-
-status_t BufferQueue::consumerConnect(const sp<ConsumerListener>& consumerListener) {
- ST_LOGV("consumerConnect");
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("consumerConnect: BufferQueue has been abandoned!");
- return NO_INIT;
- }
-
- mConsumerListener = consumerListener;
-
- return OK;
-}
-
-status_t BufferQueue::consumerDisconnect() {
- ST_LOGV("consumerDisconnect");
- Mutex::Autolock lock(mMutex);
-
- if (mConsumerListener == NULL) {
- ST_LOGE("consumerDisconnect: No consumer is connected!");
- return -EINVAL;
- }
-
- mAbandoned = true;
- mConsumerListener = NULL;
- mQueue.clear();
- freeAllBuffersLocked();
- mDequeueCondition.broadcast();
- return OK;
-}
-
-status_t BufferQueue::getReleasedBuffers(uint32_t* slotMask) {
- ST_LOGV("getReleasedBuffers");
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("getReleasedBuffers: BufferQueue has been abandoned!");
- return NO_INIT;
- }
-
- uint32_t mask = 0;
- for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- if (!mSlots[i].mAcquireCalled) {
- mask |= 1 << i;
- }
- }
- *slotMask = mask;
-
- ST_LOGV("getReleasedBuffers: returning mask %#x", mask);
- return NO_ERROR;
-}
-
-status_t BufferQueue::setDefaultBufferSize(uint32_t w, uint32_t h)
-{
- ST_LOGV("setDefaultBufferSize: w=%d, h=%d", w, h);
- if (!w || !h) {
- ST_LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)",
- w, h);
- return BAD_VALUE;
- }
-
- Mutex::Autolock lock(mMutex);
- mDefaultWidth = w;
- mDefaultHeight = h;
- return OK;
-}
-
-status_t BufferQueue::setBufferCountServer(int bufferCount) {
- ATRACE_CALL();
- Mutex::Autolock lock(mMutex);
- return setBufferCountServerLocked(bufferCount);
-}
-
-void BufferQueue::freeAllBuffersExceptHeadLocked() {
- int head = -1;
- if (!mQueue.empty()) {
- Fifo::iterator front(mQueue.begin());
- head = *front;
- }
- mBufferHasBeenQueued = false;
- for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- if (i != head) {
- freeBufferLocked(i);
- }
- }
-}
-
-status_t BufferQueue::drainQueueLocked() {
- while (mSynchronousMode && !mQueue.isEmpty()) {
- mDequeueCondition.wait(mMutex);
- if (mAbandoned) {
- ST_LOGE("drainQueueLocked: BufferQueue has been abandoned!");
- return NO_INIT;
- }
- if (mConnectedApi == NO_CONNECTED_API) {
- ST_LOGE("drainQueueLocked: BufferQueue is not connected!");
- return NO_INIT;
- }
- }
- return NO_ERROR;
-}
-
-status_t BufferQueue::drainQueueAndFreeBuffersLocked() {
- status_t err = drainQueueLocked();
- if (err == NO_ERROR) {
- if (mSynchronousMode) {
- freeAllBuffersLocked();
- } else {
- freeAllBuffersExceptHeadLocked();
- }
- }
- return err;
-}
-
-BufferQueue::ProxyConsumerListener::ProxyConsumerListener(
- const wp<BufferQueue::ConsumerListener>& consumerListener):
- mConsumerListener(consumerListener) {}
-
-BufferQueue::ProxyConsumerListener::~ProxyConsumerListener() {}
-
-void BufferQueue::ProxyConsumerListener::onFrameAvailable() {
- sp<BufferQueue::ConsumerListener> listener(mConsumerListener.promote());
- if (listener != NULL) {
- listener->onFrameAvailable();
- }
-}
-
-void BufferQueue::ProxyConsumerListener::onBuffersReleased() {
- sp<BufferQueue::ConsumerListener> listener(mConsumerListener.promote());
- if (listener != NULL) {
- listener->onBuffersReleased();
- }
-}
-
-}; // namespace android
-
-#endif
diff --git a/src/imports/nativemedia/BufferQueue.h b/src/imports/nativemedia/BufferQueue.h
deleted file mode 100644
index 1c80d0c..0000000
--- a/src/imports/nativemedia/BufferQueue.h
+++ /dev/null
@@ -1,490 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_GUI_BUFFERQUEUE_H
-#define ANDROID_GUI_BUFFERQUEUE_H
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
-#include <gui/IGraphicBufferAlloc.h>
-#include <gui/ISurfaceTexture.h>
-
-#include <ui/GraphicBuffer.h>
-
-#include <utils/String8.h>
-#include <utils/Vector.h>
-#include <utils/threads.h>
-
-namespace android {
-// ----------------------------------------------------------------------------
-
-class BufferQueue : public BnSurfaceTexture {
-public:
- enum { MIN_UNDEQUEUED_BUFFERS = 2 };
- enum { NUM_BUFFER_SLOTS = 32 };
- enum { NO_CONNECTED_API = 0 };
- enum { INVALID_BUFFER_SLOT = -1 };
- enum { STALE_BUFFER_SLOT = 1, NO_BUFFER_AVAILABLE };
-
- // ConsumerListener is the interface through which the BufferQueue notifies
- // the consumer of events that the consumer may wish to react to. Because
- // the consumer will generally have a mutex that is locked during calls from
- // teh consumer to the BufferQueue, these calls from the BufferQueue to the
- // consumer *MUST* be called only when the BufferQueue mutex is NOT locked.
- struct ConsumerListener : public virtual RefBase {
- // onFrameAvailable is called from queueBuffer each time an additional
- // frame becomes available for consumption. This means that frames that
- // are queued while in asynchronous mode only trigger the callback if no
- // previous frames are pending. Frames queued while in synchronous mode
- // always trigger the callback.
- //
- // This is called without any lock held and can be called concurrently
- // by multiple threads.
- virtual void onFrameAvailable() = 0;
-
- // onBuffersReleased is called to notify the buffer consumer that the
- // BufferQueue has released its references to one or more GraphicBuffers
- // contained in its slots. The buffer consumer should then call
- // BufferQueue::getReleasedBuffers to retrieve the list of buffers
- //
- // This is called without any lock held and can be called concurrently
- // by multiple threads.
- virtual void onBuffersReleased() = 0;
- };
-
- // ProxyConsumerListener is a ConsumerListener implementation that keeps a weak
- // reference to the actual consumer object. It forwards all calls to that
- // consumer object so long as it exists.
- //
- // This class exists to avoid having a circular reference between the
- // BufferQueue object and the consumer object. The reason this can't be a weak
- // reference in the BufferQueue class is because we're planning to expose the
- // consumer side of a BufferQueue as a binder interface, which doesn't support
- // weak references.
- class ProxyConsumerListener : public BufferQueue::ConsumerListener {
- public:
-
- ProxyConsumerListener(const wp<BufferQueue::ConsumerListener>& consumerListener);
- virtual ~ProxyConsumerListener();
- virtual void onFrameAvailable();
- virtual void onBuffersReleased();
-
- private:
-
- // mConsumerListener is a weak reference to the ConsumerListener. This is
- // the raison d'etre of ProxyConsumerListener.
- wp<BufferQueue::ConsumerListener> mConsumerListener;
- };
-
-
- // BufferQueue manages a pool of gralloc memory slots to be used
- // by producers and consumers.
- // allowSynchronousMode specifies whether or not synchronous mode can be
- // enabled.
- // bufferCount sets the minimum number of undequeued buffers for this queue
- BufferQueue( bool allowSynchronousMode = true, int bufferCount = MIN_UNDEQUEUED_BUFFERS);
- virtual ~BufferQueue();
-
- virtual int query(int what, int* value);
-
- // setBufferCount updates the number of available buffer slots. After
- // calling this all buffer slots are both unallocated and owned by the
- // BufferQueue object (i.e. they are not owned by the client).
- virtual status_t setBufferCount(int bufferCount);
-
- virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);
-
- // dequeueBuffer gets the next buffer slot index for the client to use. If a
- // buffer slot is available then that slot index is written to the location
- // pointed to by the buf argument and a status of OK is returned. If no
- // slot is available then a status of -EBUSY is returned and buf is
- // unmodified.
- // The width and height parameters must be no greater than the minimum of
- // GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv).
- // An error due to invalid dimensions might not be reported until
- // updateTexImage() is called.
- virtual status_t dequeueBuffer(int *buf, uint32_t width, uint32_t height,
- uint32_t format, uint32_t usage);
-
- // queueBuffer returns a filled buffer to the BufferQueue. In addition, a
- // timestamp must be provided for the buffer. The timestamp is in
- // nanoseconds, and must be monotonically increasing. Its other semantics
- // (zero point, etc) are client-dependent and should be documented by the
- // client.
- virtual status_t queueBuffer(int buf,
- const QueueBufferInput& input, QueueBufferOutput* output);
-
- virtual void cancelBuffer(int buf);
-
- // setSynchronousMode set whether dequeueBuffer is synchronous or
- // asynchronous. In synchronous mode, dequeueBuffer blocks until
- // a buffer is available, the currently bound buffer can be dequeued and
- // queued buffers will be retired in order.
- // The default mode is asynchronous.
- virtual status_t setSynchronousMode(bool enabled);
-
- // connect attempts to connect a producer client API to the BufferQueue.
- // This must be called before any other ISurfaceTexture methods are called
- // except for getAllocator.
- //
- // This method will fail if the connect was previously called on the
- // BufferQueue and no corresponding disconnect call was made.
- virtual status_t connect(int api, QueueBufferOutput* output);
-
- // disconnect attempts to disconnect a producer client API from the
- // BufferQueue. Calling this method will cause any subsequent calls to other
- // ISurfaceTexture methods to fail except for getAllocator and connect.
- // Successfully calling connect after this will allow the other methods to
- // succeed again.
- //
- // This method will fail if the the BufferQueue is not currently
- // connected to the specified client API.
- virtual status_t disconnect(int api);
-
- // dump our state in a String
- virtual void dump(String8& result) const;
- virtual void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const;
-
- // public facing structure for BufferSlot
- struct BufferItem {
-
- BufferItem()
- :
- mTransform(0),
- mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
- mTimestamp(0),
- mFrameNumber(0),
- mBuf(INVALID_BUFFER_SLOT) {
- mCrop.makeInvalid();
- }
- // mGraphicBuffer points to the buffer allocated for this slot or is NULL
- // if no buffer has been allocated.
- sp<GraphicBuffer> mGraphicBuffer;
-
- // mCrop is the current crop rectangle for this buffer slot.
- Rect mCrop;
-
- // mTransform is the current transform flags for this buffer slot.
- uint32_t mTransform;
-
- // mScalingMode is the current scaling mode for this buffer slot.
- uint32_t mScalingMode;
-
- // mTimestamp is the current timestamp for this buffer slot. This gets
- // to set by queueBuffer each time this slot is queued.
- int64_t mTimestamp;
-
- // mFrameNumber is the number of the queued frame for this slot.
- uint64_t mFrameNumber;
-
- // mBuf is the slot index of this buffer
- int mBuf;
- };
-
- // The following public functions is the consumer facing interface
-
- // acquireBuffer attempts to acquire ownership of the next pending buffer in
- // the BufferQueue. If no buffer is pending then it returns -EINVAL. If a
- // buffer is successfully acquired, the information about the buffer is
- // returned in BufferItem. If the buffer returned had previously been
- // acquired then the BufferItem::mGraphicBuffer field of buffer is set to
- // NULL and it is assumed that the consumer still holds a reference to the
- // buffer.
- status_t acquireBuffer(BufferItem *buffer);
-
- // releaseBuffer releases a buffer slot from the consumer back to the
- // BufferQueue pending a fence sync.
- //
- // Note that the dependencies on EGL will be removed once we switch to using
- // the Android HW Sync HAL.
- status_t releaseBuffer(int buf, EGLDisplay display, EGLSyncKHR fence);
-
- // consumerConnect connects a consumer to the BufferQueue. Only one
- // consumer may be connected, and when that consumer disconnects the
- // BufferQueue is placed into the "abandoned" state, causing most
- // interactions with the BufferQueue by the producer to fail.
- status_t consumerConnect(const sp<ConsumerListener>& consumer);
-
- // consumerDisconnect disconnects a consumer from the BufferQueue. All
- // buffers will be freed and the BufferQueue is placed in the "abandoned"
- // state, causing most interactions with the BufferQueue by the producer to
- // fail.
- status_t consumerDisconnect();
-
- // getReleasedBuffers sets the value pointed to by slotMask to a bit mask
- // indicating which buffer slots the have been released by the BufferQueue
- // but have not yet been released by the consumer.
- status_t getReleasedBuffers(uint32_t* slotMask);
-
- // setDefaultBufferSize is used to set the size of buffers returned by
- // requestBuffers when a with and height of zero is requested.
- status_t setDefaultBufferSize(uint32_t w, uint32_t h);
-
- // setBufferCountServer set the buffer count. If the client has requested
- // a buffer count using setBufferCount, the server-buffer count will
- // take effect once the client sets the count back to zero.
- status_t setBufferCountServer(int bufferCount);
-
- // isSynchronousMode returns whether the SurfaceTexture is currently in
- // synchronous mode.
- bool isSynchronousMode() const;
-
- // setConsumerName sets the name used in logging
- void setConsumerName(const String8& name);
-
- // setDefaultBufferFormat allows the BufferQueue to create
- // GraphicBuffers of a defaultFormat if no format is specified
- // in dequeueBuffer
- status_t setDefaultBufferFormat(uint32_t defaultFormat);
-
- // setConsumerUsageBits will turn on additional usage bits for dequeueBuffer
- status_t setConsumerUsageBits(uint32_t usage);
-
- // setTransformHint bakes in rotation to buffers so overlays can be used
- status_t setTransformHint(uint32_t hint);
-
-private:
- // freeBufferLocked frees the resources (both GraphicBuffer and EGLImage)
- // for the given slot.
- void freeBufferLocked(int index);
-
- // freeAllBuffersLocked frees the resources (both GraphicBuffer and
- // EGLImage) for all slots.
- void freeAllBuffersLocked();
-
- // freeAllBuffersExceptHeadLocked frees the resources (both GraphicBuffer
- // and EGLImage) for all slots except the head of mQueue
- void freeAllBuffersExceptHeadLocked();
-
- // drainQueueLocked drains the buffer queue if we're in synchronous mode
- // returns immediately otherwise. It returns NO_INIT if the BufferQueue
- // became abandoned or disconnected during this call.
- status_t drainQueueLocked();
-
- // drainQueueAndFreeBuffersLocked drains the buffer queue if we're in
- // synchronous mode and free all buffers. In asynchronous mode, all buffers
- // are freed except the current buffer.
- status_t drainQueueAndFreeBuffersLocked();
-
- status_t setBufferCountServerLocked(int bufferCount);
-
- struct BufferSlot {
-
- BufferSlot()
- : mEglDisplay(EGL_NO_DISPLAY),
- mBufferState(BufferSlot::FREE),
- mRequestBufferCalled(false),
- mTransform(0),
- mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
- mTimestamp(0),
- mFrameNumber(0),
- mFence(EGL_NO_SYNC_KHR),
- mAcquireCalled(false),
- mNeedsCleanupOnRelease(false) {
- mCrop.makeInvalid();
- }
-
- // mGraphicBuffer points to the buffer allocated for this slot or is NULL
- // if no buffer has been allocated.
- sp<GraphicBuffer> mGraphicBuffer;
-
- // mEglDisplay is the EGLDisplay used to create mEglImage.
- EGLDisplay mEglDisplay;
-
- // BufferState represents the different states in which a buffer slot
- // can be.
- enum BufferState {
- // FREE indicates that the buffer is not currently being used and
- // will not be used in the future until it gets dequeued and
- // subsequently queued by the client.
- // aka "owned by BufferQueue, ready to be dequeued"
- FREE = 0,
-
- // DEQUEUED indicates that the buffer has been dequeued by the
- // client, but has not yet been queued or canceled. The buffer is
- // considered 'owned' by the client, and the server should not use
- // it for anything.
- //
- // Note that when in synchronous-mode (mSynchronousMode == true),
- // the buffer that's currently attached to the texture may be
- // dequeued by the client. That means that the current buffer can
- // be in either the DEQUEUED or QUEUED state. In asynchronous mode,
- // however, the current buffer is always in the QUEUED state.
- // aka "owned by producer, ready to be queued"
- DEQUEUED = 1,
-
- // QUEUED indicates that the buffer has been queued by the client,
- // and has not since been made available for the client to dequeue.
- // Attaching the buffer to the texture does NOT transition the
- // buffer away from the QUEUED state. However, in Synchronous mode
- // the current buffer may be dequeued by the client under some
- // circumstances. See the note about the current buffer in the
- // documentation for DEQUEUED.
- // aka "owned by BufferQueue, ready to be acquired"
- QUEUED = 2,
-
- // aka "owned by consumer, ready to be released"
- ACQUIRED = 3
- };
-
- // mBufferState is the current state of this buffer slot.
- BufferState mBufferState;
-
- // mRequestBufferCalled is used for validating that the client did
- // call requestBuffer() when told to do so. Technically this is not
- // needed but useful for debugging and catching client bugs.
- bool mRequestBufferCalled;
-
- // mCrop is the current crop rectangle for this buffer slot.
- Rect mCrop;
-
- // mTransform is the current transform flags for this buffer slot.
- uint32_t mTransform;
-
- // mScalingMode is the current scaling mode for this buffer slot.
- uint32_t mScalingMode;
-
- // mTimestamp is the current timestamp for this buffer slot. This gets
- // to set by queueBuffer each time this slot is queued.
- int64_t mTimestamp;
-
- // mFrameNumber is the number of the queued frame for this slot.
- uint64_t mFrameNumber;
-
- // mFence is the EGL sync object that must signal before the buffer
- // associated with this buffer slot may be dequeued. It is initialized
- // to EGL_NO_SYNC_KHR when the buffer is created and (optionally, based
- // on a compile-time option) set to a new sync object in updateTexImage.
- EGLSyncKHR mFence;
-
- // Indicates whether this buffer has been seen by a consumer yet
- bool mAcquireCalled;
-
- // Indicates whether this buffer needs to be cleaned up by consumer
- bool mNeedsCleanupOnRelease;
- };
-
- // mSlots is the array of buffer slots that must be mirrored on the client
- // side. This allows buffer ownership to be transferred between the client
- // and server without sending a GraphicBuffer over binder. The entire array
- // is initialized to NULL at construction time, and buffers are allocated
- // for a slot when requestBuffer is called with that slot's index.
- BufferSlot mSlots[NUM_BUFFER_SLOTS];
-
- // mDefaultWidth holds the default width of allocated buffers. It is used
- // in requestBuffers() if a width and height of zero is specified.
- uint32_t mDefaultWidth;
-
- // mDefaultHeight holds the default height of allocated buffers. It is used
- // in requestBuffers() if a width and height of zero is specified.
- uint32_t mDefaultHeight;
-
- // mPixelFormat holds the pixel format of allocated buffers. It is used
- // in requestBuffers() if a format of zero is specified.
- uint32_t mPixelFormat;
-
- // mMinUndequeuedBuffers is a constraint on the number of buffers
- // not dequeued at any time
- int mMinUndequeuedBuffers;
-
- // mMinAsyncBufferSlots is a constraint on the minimum mBufferCount
- // when this BufferQueue is in asynchronous mode
- int mMinAsyncBufferSlots;
-
- // mMinSyncBufferSlots is a constraint on the minimum mBufferCount
- // when this BufferQueue is in synchronous mode
- int mMinSyncBufferSlots;
-
- // mBufferCount is the number of buffer slots that the client and server
- // must maintain. It defaults to MIN_ASYNC_BUFFER_SLOTS and can be changed
- // by calling setBufferCount or setBufferCountServer
- int mBufferCount;
-
- // mClientBufferCount is the number of buffer slots requested by the client.
- // The default is zero, which means the client doesn't care how many buffers
- // there is.
- int mClientBufferCount;
-
- // mServerBufferCount buffer count requested by the server-side
- int mServerBufferCount;
-
- // mGraphicBufferAlloc is the connection to SurfaceFlinger that is used to
- // allocate new GraphicBuffer objects.
- sp<IGraphicBufferAlloc> mGraphicBufferAlloc;
-
- // mConsumerListener is used to notify the connected consumer of
- // asynchronous events that it may wish to react to. It is initially set
- // to NULL and is written by consumerConnect and consumerDisconnect.
- sp<ConsumerListener> mConsumerListener;
-
- // mSynchronousMode whether we're in synchronous mode or not
- bool mSynchronousMode;
-
- // mAllowSynchronousMode whether we allow synchronous mode or not
- const bool mAllowSynchronousMode;
-
- // mConnectedApi indicates the API that is currently connected to this
- // BufferQueue. It defaults to NO_CONNECTED_API (= 0), and gets updated
- // by the connect and disconnect methods.
- int mConnectedApi;
-
- // mDequeueCondition condition used for dequeueBuffer in synchronous mode
- mutable Condition mDequeueCondition;
-
- // mQueue is a FIFO of queued buffers used in synchronous mode
- typedef Vector<int> Fifo;
- Fifo mQueue;
-
- // mAbandoned indicates that the BufferQueue will no longer be used to
- // consume images buffers pushed to it using the ISurfaceTexture interface.
- // It is initialized to false, and set to true in the abandon method. A
- // BufferQueue that has been abandoned will return the NO_INIT error from
- // all ISurfaceTexture methods capable of returning an error.
- bool mAbandoned;
-
- // mName is a string used to identify the BufferQueue in log messages.
- // It is set by the setName method.
- String8 mConsumerName;
-
- // mMutex is the mutex used to prevent concurrent access to the member
- // variables of BufferQueue objects. It must be locked whenever the
- // member variables are accessed.
- mutable Mutex mMutex;
-
- // mFrameCounter is the free running counter, incremented for every buffer queued
- // with the surface Texture.
- uint64_t mFrameCounter;
-
- // mBufferHasBeenQueued is true once a buffer has been queued. It is reset
- // by changing the buffer count.
- bool mBufferHasBeenQueued;
-
- // mDefaultBufferFormat can be set so it will override
- // the buffer format when it isn't specified in dequeueBuffer
- uint32_t mDefaultBufferFormat;
-
- // mConsumerUsageBits contains flags the consumer wants for GraphicBuffers
- uint32_t mConsumerUsageBits;
-
- // mTransformHint is used to optimize for screen rotations
- uint32_t mTransformHint;
-};
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_GUI_BUFFERQUEUE_H
diff --git a/src/imports/nativemedia/SurfaceTexture.cpp b/src/imports/nativemedia/SurfaceTexture.cpp
deleted file mode 100644
index 05207ad..0000000
--- a/src/imports/nativemedia/SurfaceTexture.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#if Q_ANDROID_VERSION_MAJOR > 4 || (Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR >= 1)
-#include "SurfaceTexture_4_1.cpp"
-#else
-#include "SurfaceTexture_4_0.cpp"
-#endif
diff --git a/src/imports/nativemedia/SurfaceTexture.h b/src/imports/nativemedia/SurfaceTexture.h
deleted file mode 100644
index 552d465..0000000
--- a/src/imports/nativemedia/SurfaceTexture.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#if Q_ANDROID_VERSION_MAJOR > 4 || (Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR >= 1)
-#include "SurfaceTexture_4_1.h"
-#else
-#include "SurfaceTexture_4_0.h"
-#endif
diff --git a/src/imports/nativemedia/SurfaceTexture_4_0.cpp b/src/imports/nativemedia/SurfaceTexture_4_0.cpp
deleted file mode 100644
index 1ec08a7..0000000
--- a/src/imports/nativemedia/SurfaceTexture_4_0.cpp
+++ /dev/null
@@ -1,1236 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "SurfaceTexture"
-//#define LOG_NDEBUG 0
-
-#define GL_GLEXT_PROTOTYPES
-#define EGL_EGLEXT_PROTOTYPES
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
-#include <SurfaceTexture.h>
-
-#include <hardware/hardware.h>
-
-#include <surfaceflinger/SurfaceComposerClient.h>
-#include <surfaceflinger/IGraphicBufferAlloc.h>
-
-#include <utils/Log.h>
-#include <utils/String8.h>
-
-#include <QtDebug>
-
-// This compile option causes SurfaceTexture to return the buffer that is currently
-// attached to the GL texture from dequeueBuffer when no other buffers are
-// available. It requires the drivers (Gralloc, GL, OMX IL, and Camera) to do
-// implicit cross-process synchronization to prevent the buffer from being
-// written to before the buffer has (a) been detached from the GL texture and
-// (b) all GL reads from the buffer have completed.
-#ifdef ALLOW_DEQUEUE_CURRENT_BUFFER
-#define FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER true
-#warning "ALLOW_DEQUEUE_CURRENT_BUFFER enabled"
-#else
-#define FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER false
-#endif
-
-// This compile option makes SurfaceTexture use the EGL_KHR_fence_sync extension
-// to synchronize access to the buffers. It will cause dequeueBuffer to stall,
-// waiting for the GL reads for the buffer being dequeued to complete before
-// allowing the buffer to be dequeued.
-#ifdef USE_FENCE_SYNC
-#ifdef ALLOW_DEQUEUE_CURRENT_BUFFER
-#error "USE_FENCE_SYNC and ALLOW_DEQUEUE_CURRENT_BUFFER are incompatible"
-#endif
-#endif
-
-// Macros for including the SurfaceTexture name in log messages
-#if 0
-#define ST_LOGV(x, ...) LOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define ST_LOGD(x, ...) LOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define ST_LOGI(x, ...) LOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define ST_LOGW(x, ...) LOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
-#define ST_LOGE(x, ...) LOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
-#else
-#define ST_LOGV(x, ...) LOGV("[V/%s] "x, mName.string(), ##__VA_ARGS__)
-#define ST_LOGD(x, ...) LOGD("[D/%s] "x, mName.string(), ##__VA_ARGS__)
-#define ST_LOGI(x, ...) qDebug("[I/%s] "x, mName.string(), ##__VA_ARGS__)
-#define ST_LOGW(x, ...) qDebug("[W/%s] "x, mName.string(), ##__VA_ARGS__)
-#define ST_LOGE(x, ...) qDebug("[E/%s] "x, mName.string(), ##__VA_ARGS__)
-#endif
-
-namespace android {
-
-// Transform matrices
-static float mtxIdentity[16] = {
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1,
-};
-static float mtxFlipH[16] = {
- -1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 1, 0, 0, 1,
-};
-static float mtxFlipV[16] = {
- 1, 0, 0, 0,
- 0, -1, 0, 0,
- 0, 0, 1, 0,
- 0, 1, 0, 1,
-};
-static float mtxRot90[16] = {
- 0, 1, 0, 0,
- -1, 0, 0, 0,
- 0, 0, 1, 0,
- 1, 0, 0, 1,
-};
-static float mtxRot180[16] = {
- -1, 0, 0, 0,
- 0, -1, 0, 0,
- 0, 0, 1, 0,
- 1, 1, 0, 1,
-};
-static float mtxRot270[16] = {
- 0, -1, 0, 0,
- 1, 0, 0, 0,
- 0, 0, 1, 0,
- 0, 1, 0, 1,
-};
-
-static void mtxMul(float out[16], const float a[16], const float b[16]);
-
-// Get an ID that's unique within this process.
-static int32_t createProcessUniqueId() {
- static volatile int32_t globalCounter = 0;
- return android_atomic_inc(&globalCounter);
-}
-
-SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode,
- GLenum texTarget, bool useFenceSync) :
- mDefaultWidth(1),
- mDefaultHeight(1),
- mPixelFormat(PIXEL_FORMAT_RGBA_8888),
- mBufferCount(MIN_ASYNC_BUFFER_SLOTS),
- mClientBufferCount(0),
- mServerBufferCount(MIN_ASYNC_BUFFER_SLOTS),
- mCurrentTexture(INVALID_BUFFER_SLOT),
- mCurrentTransform(0),
- mCurrentTimestamp(0),
- mNextTransform(0),
- mNextScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
- mTexName(tex),
- mSynchronousMode(false),
- mAllowSynchronousMode(allowSynchronousMode),
- mConnectedApi(NO_CONNECTED_API),
- mAbandoned(false),
-#ifdef USE_FENCE_SYNC
- mUseFenceSync(useFenceSync),
-#else
- mUseFenceSync(false),
-#endif
- mTexTarget(texTarget),
- mFrameCounter(0) {
- // Choose a name using the PID and a process-unique ID.
- mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
-
- ST_LOGV("SurfaceTexture");
-// sp<ISurfaceComposer> composer(ComposerService::getComposerService());
-// mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
- mNextCrop.makeInvalid();
- memcpy(mCurrentTransformMatrix, mtxIdentity,
- sizeof(mCurrentTransformMatrix));
-}
-
-SurfaceTexture::~SurfaceTexture() {
- ST_LOGV("~SurfaceTexture");
- freeAllBuffersLocked();
-}
-
-status_t SurfaceTexture::setBufferCountServerLocked(int bufferCount) {
- if (bufferCount > NUM_BUFFER_SLOTS)
- return BAD_VALUE;
-
- // special-case, nothing to do
- if (bufferCount == mBufferCount)
- return OK;
-
- if (!mClientBufferCount &&
- bufferCount >= mBufferCount) {
- // easy, we just have more buffers
- mBufferCount = bufferCount;
- mServerBufferCount = bufferCount;
- mDequeueCondition.signal();
- } else {
- // we're here because we're either
- // - reducing the number of available buffers
- // - or there is a client-buffer-count in effect
-
- // less than 2 buffers is never allowed
- if (bufferCount < 2)
- return BAD_VALUE;
-
- // when there is non client-buffer-count in effect, the client is not
- // allowed to dequeue more than one buffer at a time,
- // so the next time they dequeue a buffer, we know that they don't
- // own one. the actual resizing will happen during the next
- // dequeueBuffer.
-
- mServerBufferCount = bufferCount;
- }
- return OK;
-}
-
-status_t SurfaceTexture::setBufferCountServer(int bufferCount) {
- Mutex::Autolock lock(mMutex);
- return setBufferCountServerLocked(bufferCount);
-}
-
-status_t SurfaceTexture::setBufferCount(int bufferCount) {
- ST_LOGV("setBufferCount: count=%d", bufferCount);
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("setBufferCount: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
- if (bufferCount > NUM_BUFFER_SLOTS) {
- ST_LOGE("setBufferCount: bufferCount larger than slots available");
- return BAD_VALUE;
- }
-
- // Error out if the user has dequeued buffers
- for (int i=0 ; i<mBufferCount ; i++) {
- if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
- ST_LOGE("setBufferCount: client owns some buffers");
- return -EINVAL;
- }
- }
-
- const int minBufferSlots = mSynchronousMode ?
- MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
- if (bufferCount == 0) {
- mClientBufferCount = 0;
- bufferCount = (mServerBufferCount >= minBufferSlots) ?
- mServerBufferCount : minBufferSlots;
- return setBufferCountServerLocked(bufferCount);
- }
-
- if (bufferCount < minBufferSlots) {
- ST_LOGE("setBufferCount: requested buffer count (%d) is less than "
- "minimum (%d)", bufferCount, minBufferSlots);
- return BAD_VALUE;
- }
-
- // here we're guaranteed that the client doesn't have dequeued buffers
- // and will release all of its buffer references.
- freeAllBuffersLocked();
- mBufferCount = bufferCount;
- mClientBufferCount = bufferCount;
- mCurrentTexture = INVALID_BUFFER_SLOT;
- mQueue.clear();
- mDequeueCondition.signal();
- return OK;
-}
-
-status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h)
-{
- ST_LOGV("setDefaultBufferSize: w=%d, h=%d", w, h);
- if (!w || !h) {
- ST_LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)",
- w, h);
- return BAD_VALUE;
- }
-
- Mutex::Autolock lock(mMutex);
- mDefaultWidth = w;
- mDefaultHeight = h;
- return OK;
-}
-
-status_t SurfaceTexture::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
- ST_LOGV("requestBuffer: slot=%d", slot);
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- ST_LOGE("requestBuffer: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
- if (slot < 0 || mBufferCount <= slot) {
- ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d",
- mBufferCount, slot);
- return BAD_VALUE;
- }
- mSlots[slot].mRequestBufferCalled = true;
- *buf = mSlots[slot].mGraphicBuffer;
- return NO_ERROR;
-}
-
-status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
- uint32_t format, uint32_t usage) {
- ST_LOGV("dequeueBuffer: w=%d h=%d fmt=%#x usage=%#x", w, h, format, usage);
-
- if ((w && !h) || (!w && h)) {
- ST_LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
- return BAD_VALUE;
- }
-
- status_t returnFlags(OK);
- EGLDisplay dpy = EGL_NO_DISPLAY;
- EGLSyncKHR fence = EGL_NO_SYNC_KHR;
-
- { // Scope for the lock
- Mutex::Autolock lock(mMutex);
-
- int found = -1;
- int foundSync = -1;
- int dequeuedCount = 0;
- bool tryAgain = true;
- while (tryAgain) {
- if (mAbandoned) {
- ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
-
- // We need to wait for the FIFO to drain if the number of buffer
- // needs to change.
- //
- // The condition "number of buffers needs to change" is true if
- // - the client doesn't care about how many buffers there are
- // - AND the actual number of buffer is different from what was
- // set in the last setBufferCountServer()
- // - OR -
- // setBufferCountServer() was set to a value incompatible with
- // the synchronization mode (for instance because the sync mode
- // changed since)
- //
- // As long as this condition is true AND the FIFO is not empty, we
- // wait on mDequeueCondition.
-
- const int minBufferCountNeeded = mSynchronousMode ?
- MIN_SYNC_BUFFER_SLOTS : MIN_ASYNC_BUFFER_SLOTS;
-
- const bool numberOfBuffersNeedsToChange = !mClientBufferCount &&
- ((mServerBufferCount != mBufferCount) ||
- (mServerBufferCount < minBufferCountNeeded));
-
- if (!mQueue.isEmpty() && numberOfBuffersNeedsToChange) {
- // wait for the FIFO to drain
- mDequeueCondition.wait(mMutex);
- // NOTE: we continue here because we need to reevaluate our
- // whole state (eg: we could be abandoned or disconnected)
- continue;
- }
-
- if (numberOfBuffersNeedsToChange) {
- // here we're guaranteed that mQueue is empty
- freeAllBuffersLocked();
- mBufferCount = mServerBufferCount;
- if (mBufferCount < minBufferCountNeeded)
- mBufferCount = minBufferCountNeeded;
- mCurrentTexture = INVALID_BUFFER_SLOT;
- returnFlags |= ISurfaceTexture::RELEASE_ALL_BUFFERS;
- }
-
- // look for a free buffer to give to the client
- found = INVALID_BUFFER_SLOT;
- foundSync = INVALID_BUFFER_SLOT;
- dequeuedCount = 0;
- for (int i = 0; i < mBufferCount; i++) {
- const int state = mSlots[i].mBufferState;
- if (state == BufferSlot::DEQUEUED) {
- dequeuedCount++;
- }
-
- // if buffer is FREE it CANNOT be current
- LOGW_IF((state == BufferSlot::FREE) && (mCurrentTexture==i),
- "dequeueBuffer: buffer %d is both FREE and current!",
- i);
-
- if (FLAG_ALLOW_DEQUEUE_CURRENT_BUFFER) {
- if (state == BufferSlot::FREE || i == mCurrentTexture) {
- foundSync = i;
- if (i != mCurrentTexture) {
- found = i;
- break;
- }
- }
- } else {
- if (state == BufferSlot::FREE) {
- /* We return the oldest of the free buffers to avoid
- * stalling the producer if possible. This is because
- * the consumer may still have pending reads of the
- * buffers in flight.
- */
- bool isOlder = mSlots[i].mFrameNumber <
- mSlots[found].mFrameNumber;
- if (found < 0 || isOlder) {
- foundSync = i;
- found = i;
- }
- }
- }
- }
-
- // clients are not allowed to dequeue more than one buffer
- // if they didn't set a buffer count.
- if (!mClientBufferCount && dequeuedCount) {
- ST_LOGE("dequeueBuffer: can't dequeue multiple buffers without "
- "setting the buffer count");
- return -EINVAL;
- }
-
- // See whether a buffer has been queued since the last
- // setBufferCount so we know whether to perform the
- // MIN_UNDEQUEUED_BUFFERS check below.
- bool bufferHasBeenQueued = mCurrentTexture != INVALID_BUFFER_SLOT;
- if (bufferHasBeenQueued) {
- // make sure the client is not trying to dequeue more buffers
- // than allowed.
- const int avail = mBufferCount - (dequeuedCount+1);
- if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) {
- ST_LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded "
- "(dequeued=%d)",
- MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode),
- dequeuedCount);
- return -EBUSY;
- }
- }
-
- // we're in synchronous mode and didn't find a buffer, we need to
- // wait for some buffers to be consumed
- tryAgain = mSynchronousMode && (foundSync == INVALID_BUFFER_SLOT);
- if (tryAgain) {
- mDequeueCondition.wait(mMutex);
- }
- }
-
- if (mSynchronousMode && found == INVALID_BUFFER_SLOT) {
- // foundSync guaranteed to be != INVALID_BUFFER_SLOT
- found = foundSync;
- }
-
- if (found == INVALID_BUFFER_SLOT) {
- // This should not happen.
- ST_LOGE("dequeueBuffer: no available buffer slots");
- return -EBUSY;
- }
-
- const int buf = found;
- *outBuf = found;
-
- const bool useDefaultSize = !w && !h;
- if (useDefaultSize) {
- // use the default size
- w = mDefaultWidth;
- h = mDefaultHeight;
- }
-
- const bool updateFormat = (format != 0);
- if (!updateFormat) {
- // keep the current (or default) format
- format = mPixelFormat;
- }
-
- // buffer is now in DEQUEUED (but can also be current at the same time,
- // if we're in synchronous mode)
- mSlots[buf].mBufferState = BufferSlot::DEQUEUED;
-
- const sp<GraphicBuffer>& buffer(mSlots[buf].mGraphicBuffer);
- if ((buffer == NULL) ||
- (uint32_t(buffer->width) != w) ||
- (uint32_t(buffer->height) != h) ||
- (uint32_t(buffer->format) != format) ||
- ((uint32_t(buffer->usage) & usage) != usage))
- {
- usage |= GraphicBuffer::USAGE_HW_TEXTURE;
- status_t error;
- sp<GraphicBuffer> graphicBuffer(
- new GraphicBuffer(w, h, format, usage));
-// mGraphicBufferAlloc->createGraphicBuffer(
-// w, h, format, usage, &error));
- if (graphicBuffer == 0) {
- ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer "
- "failed");
- return error;
- }
- if (updateFormat) {
- mPixelFormat = format;
- }
- mSlots[buf].mGraphicBuffer = graphicBuffer;
- mSlots[buf].mRequestBufferCalled = false;
- mSlots[buf].mFence = EGL_NO_SYNC_KHR;
- if (mSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) {
- eglDestroyImageKHR(mSlots[buf].mEglDisplay,
- mSlots[buf].mEglImage);
- mSlots[buf].mEglImage = EGL_NO_IMAGE_KHR;
- mSlots[buf].mEglDisplay = EGL_NO_DISPLAY;
- }
- if (mCurrentTexture == buf) {
- // The current texture no longer references the buffer in this slot
- // since we just allocated a new buffer.
- mCurrentTexture = INVALID_BUFFER_SLOT;
- }
- returnFlags |= ISurfaceTexture::BUFFER_NEEDS_REALLOCATION;
- }
-
- dpy = mSlots[buf].mEglDisplay;
- fence = mSlots[buf].mFence;
- mSlots[buf].mFence = EGL_NO_SYNC_KHR;
- }
-
- if (fence != EGL_NO_SYNC_KHR) {
- EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
- // If something goes wrong, log the error, but return the buffer without
- // synchronizing access to it. It's too late at this point to abort the
- // dequeue operation.
- if (result == EGL_FALSE) {
- LOGE("dequeueBuffer: error waiting for fence: %#x", eglGetError());
- } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
- LOGE("dequeueBuffer: timeout waiting for fence");
- }
- eglDestroySyncKHR(dpy, fence);
- }
-
- ST_LOGV("dequeueBuffer: returning slot=%d buf=%p flags=%#x", *outBuf,
- mSlots[*outBuf].mGraphicBuffer->handle, returnFlags);
-
- return returnFlags;
-}
-
-status_t SurfaceTexture::setSynchronousMode(bool enabled) {
- ST_LOGV("setSynchronousMode: enabled=%d", enabled);
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("setSynchronousMode: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
-
- status_t err = OK;
- if (!mAllowSynchronousMode && enabled)
- return err;
-
- if (!enabled) {
- // going to asynchronous mode, drain the queue
- err = drainQueueLocked();
- if (err != NO_ERROR)
- return err;
- }
-
- if (mSynchronousMode != enabled) {
- // - if we're going to asynchronous mode, the queue is guaranteed to be
- // empty here
- // - if the client set the number of buffers, we're guaranteed that
- // we have at least 3 (because we don't allow less)
- mSynchronousMode = enabled;
- mDequeueCondition.signal();
- }
- return err;
-}
-
-status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp,
- uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
- ST_LOGV("queueBuffer: slot=%d time=%lld", buf, timestamp);
-
- sp<FrameAvailableListener> listener;
-
- { // scope for the lock
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- ST_LOGE("queueBuffer: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
- if (buf < 0 || buf >= mBufferCount) {
- ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d",
- mBufferCount, buf);
- return -EINVAL;
- } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
- ST_LOGE("queueBuffer: slot %d is not owned by the client "
- "(state=%d)", buf, mSlots[buf].mBufferState);
- return -EINVAL;
- } else if (buf == mCurrentTexture) {
- ST_LOGE("queueBuffer: slot %d is current!", buf);
- return -EINVAL;
- } else if (!mSlots[buf].mRequestBufferCalled) {
- ST_LOGE("queueBuffer: slot %d was enqueued without requesting a "
- "buffer", buf);
- return -EINVAL;
- }
-
- if (mSynchronousMode) {
- // In synchronous mode we queue all buffers in a FIFO.
- mQueue.push_back(buf);
-
- // Synchronous mode always signals that an additional frame should
- // be consumed.
- listener = mFrameAvailableListener;
- } else {
- // In asynchronous mode we only keep the most recent buffer.
- if (mQueue.empty()) {
- mQueue.push_back(buf);
-
- // Asynchronous mode only signals that a frame should be
- // consumed if no previous frame was pending. If a frame were
- // pending then the consumer would have already been notified.
- listener = mFrameAvailableListener;
- } else {
- Fifo::iterator front(mQueue.begin());
- // buffer currently queued is freed
- mSlots[*front].mBufferState = BufferSlot::FREE;
- // and we record the new buffer index in the queued list
- *front = buf;
- }
- }
-
- mSlots[buf].mBufferState = BufferSlot::QUEUED;
- mSlots[buf].mCrop = mNextCrop;
- mSlots[buf].mTransform = mNextTransform;
- mSlots[buf].mScalingMode = mNextScalingMode;
- mSlots[buf].mTimestamp = timestamp;
- mFrameCounter++;
- mSlots[buf].mFrameNumber = mFrameCounter;
-
- mDequeueCondition.signal();
-
- *outWidth = mDefaultWidth;
- *outHeight = mDefaultHeight;
- *outTransform = 0;
- } // scope for the lock
-
- // call back without lock held
- if (listener != 0) {
- listener->onFrameAvailable();
- }
- return OK;
-}
-
-void SurfaceTexture::cancelBuffer(int buf) {
- ST_LOGV("cancelBuffer: slot=%d", buf);
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGW("cancelBuffer: SurfaceTexture has been abandoned!");
- return;
- }
-
- if (buf < 0 || buf >= mBufferCount) {
- ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
- mBufferCount, buf);
- return;
- } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
- ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
- buf, mSlots[buf].mBufferState);
- return;
- }
- mSlots[buf].mBufferState = BufferSlot::FREE;
- mSlots[buf].mFrameNumber = 0;
- mDequeueCondition.signal();
-}
-
-status_t SurfaceTexture::setCrop(const Rect& crop) {
- ST_LOGV("setCrop: crop=[%d,%d,%d,%d]", crop.left, crop.top, crop.right,
- crop.bottom);
-
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- ST_LOGE("setCrop: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
- mNextCrop = crop;
- return OK;
-}
-
-status_t SurfaceTexture::setTransform(uint32_t transform) {
- ST_LOGV("setTransform: xform=%#x", transform);
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- ST_LOGE("setTransform: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
- mNextTransform = transform;
- return OK;
-}
-
-status_t SurfaceTexture::connect(int api,
- uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
- ST_LOGV("connect: api=%d", api);
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("connect: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
-
- int err = NO_ERROR;
- switch (api) {
- case NATIVE_WINDOW_API_EGL:
- case NATIVE_WINDOW_API_CPU:
- case NATIVE_WINDOW_API_MEDIA:
- case NATIVE_WINDOW_API_CAMERA:
- if (mConnectedApi != NO_CONNECTED_API) {
- ST_LOGE("connect: already connected (cur=%d, req=%d)",
- mConnectedApi, api);
- err = -EINVAL;
- } else {
- mConnectedApi = api;
- *outWidth = mDefaultWidth;
- *outHeight = mDefaultHeight;
- *outTransform = 0;
- }
- break;
- default:
- err = -EINVAL;
- break;
- }
- return err;
-}
-
-status_t SurfaceTexture::disconnect(int api) {
- ST_LOGV("disconnect: api=%d", api);
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- // it is not really an error to disconnect after the surface
- // has been abandoned, it should just be a no-op.
- return NO_ERROR;
- }
-
- int err = NO_ERROR;
- switch (api) {
- case NATIVE_WINDOW_API_EGL:
- case NATIVE_WINDOW_API_CPU:
- case NATIVE_WINDOW_API_MEDIA:
- case NATIVE_WINDOW_API_CAMERA:
- if (mConnectedApi == api) {
- drainQueueAndFreeBuffersLocked();
- mConnectedApi = NO_CONNECTED_API;
- mNextCrop.makeInvalid();
- mNextScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
- mNextTransform = 0;
- mDequeueCondition.signal();
- } else {
- ST_LOGE("disconnect: connected to another api (cur=%d, req=%d)",
- mConnectedApi, api);
- err = -EINVAL;
- }
- break;
- default:
- ST_LOGE("disconnect: unknown API %d", api);
- err = -EINVAL;
- break;
- }
- return err;
-}
-
-status_t SurfaceTexture::setScalingMode(int mode) {
- ST_LOGV("setScalingMode: mode=%d", mode);
-
- switch (mode) {
- case NATIVE_WINDOW_SCALING_MODE_FREEZE:
- case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
- break;
- default:
- ST_LOGE("unknown scaling mode: %d", mode);
- return BAD_VALUE;
- }
-
- Mutex::Autolock lock(mMutex);
- mNextScalingMode = mode;
- return OK;
-}
-
-status_t SurfaceTexture::updateTexImage() {
- ST_LOGV("updateTexImage");
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- qDebug("calling updateTexImage() on an abandoned SurfaceTexture");
- return NO_INIT;
- }
-
- // In asynchronous mode the list is guaranteed to be one buffer
- // deep, while in synchronous mode we use the oldest buffer.
- if (!mQueue.empty()) {
- Fifo::iterator front(mQueue.begin());
- int buf = *front;
-
- // Update the GL texture object.
- EGLImageKHR image = mSlots[buf].mEglImage;
- EGLDisplay dpy = eglGetCurrentDisplay();
- if (image == EGL_NO_IMAGE_KHR) {
- if (mSlots[buf].mGraphicBuffer == 0) {
- qDebug("buffer at slot %d is null", buf);
- return BAD_VALUE;
- }
- image = createImage(dpy, mSlots[buf].mGraphicBuffer);
- mSlots[buf].mEglImage = image;
- mSlots[buf].mEglDisplay = dpy;
- if (image == EGL_NO_IMAGE_KHR) {
- // NOTE: if dpy was invalid, createImage() is guaranteed to
- // fail. so we'd end up here.
- qDebug("EGL_NO_IMAGE_KHR: %p", dpy);
- return -EINVAL;
- }
- }
-
- GLint error;
- while ((error = glGetError()) != GL_NO_ERROR) {
- ST_LOGW("updateTexImage: clearing GL error: %#04x", error);
- }
-
- glBindTexture(mTexTarget, mTexName);
- glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
-
- bool failed = false;
- while ((error = glGetError()) != GL_NO_ERROR) {
- ST_LOGE("error binding external texture image %p (slot %d): %#04x",
- image, buf, error);
- failed = true;
- }
- if (failed) {
- return -EINVAL;
- }
-
- if (mCurrentTexture != INVALID_BUFFER_SLOT) {
- if (mUseFenceSync) {
- EGLSyncKHR fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR,
- NULL);
- if (fence == EGL_NO_SYNC_KHR) {
- ST_LOGE("updateTexImage: error creating fence: %#x",
- eglGetError());
- return -EINVAL;
- }
- glFlush();
- mSlots[mCurrentTexture].mFence = fence;
- }
- }
-
- ST_LOGV("updateTexImage: (slot=%d buf=%p) -> (slot=%d buf=%p)",
- mCurrentTexture,
- mCurrentTextureBuf != NULL ? mCurrentTextureBuf->handle : 0,
- buf, mSlots[buf].mGraphicBuffer->handle);
-
- if (mCurrentTexture != INVALID_BUFFER_SLOT) {
- // The current buffer becomes FREE if it was still in the queued
- // state. If it has already been given to the client
- // (synchronous mode), then it stays in DEQUEUED state.
- if (mSlots[mCurrentTexture].mBufferState == BufferSlot::QUEUED) {
- mSlots[mCurrentTexture].mBufferState = BufferSlot::FREE;
- }
- }
-
- // Update the SurfaceTexture state.
- mCurrentTexture = buf;
- mCurrentTextureBuf = mSlots[buf].mGraphicBuffer;
- mCurrentCrop = mSlots[buf].mCrop;
- mCurrentTransform = mSlots[buf].mTransform;
- mCurrentScalingMode = mSlots[buf].mScalingMode;
- mCurrentTimestamp = mSlots[buf].mTimestamp;
- computeCurrentTransformMatrix();
-
- // Now that we've passed the point at which failures can happen,
- // it's safe to remove the buffer from the front of the queue.
- mQueue.erase(front);
- mDequeueCondition.signal();
- } else {
- // We always bind the texture even if we don't update its contents.
- glBindTexture(mTexTarget, mTexName);
- }
-
- return OK;
-}
-
-bool SurfaceTexture::isExternalFormat(uint32_t format)
-{
- switch (format) {
- // supported YUV formats
- case HAL_PIXEL_FORMAT_YV12:
- // Legacy/deprecated YUV formats
- case HAL_PIXEL_FORMAT_YCbCr_422_SP:
- case HAL_PIXEL_FORMAT_YCrCb_420_SP:
- case HAL_PIXEL_FORMAT_YCbCr_422_I:
- return true;
- }
-
- // Any OEM format needs to be considered
- if (format>=0x100 && format<=0x1FF)
- return true;
-
- return false;
-}
-
-GLenum SurfaceTexture::getCurrentTextureTarget() const {
- return mTexTarget;
-}
-
-void SurfaceTexture::getTransformMatrix(float mtx[16]) {
- Mutex::Autolock lock(mMutex);
- memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
-}
-
-void SurfaceTexture::computeCurrentTransformMatrix() {
- ST_LOGV("computeCurrentTransformMatrix");
-
- float xform[16];
- for (int i = 0; i < 16; i++) {
- xform[i] = mtxIdentity[i];
- }
- if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
- float result[16];
- mtxMul(result, xform, mtxFlipH);
- for (int i = 0; i < 16; i++) {
- xform[i] = result[i];
- }
- }
- if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
- float result[16];
- mtxMul(result, xform, mtxFlipV);
- for (int i = 0; i < 16; i++) {
- xform[i] = result[i];
- }
- }
- if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
- float result[16];
- mtxMul(result, xform, mtxRot90);
- for (int i = 0; i < 16; i++) {
- xform[i] = result[i];
- }
- }
-
- sp<GraphicBuffer>& buf(mSlots[mCurrentTexture].mGraphicBuffer);
- float tx, ty, sx, sy;
- if (!mCurrentCrop.isEmpty()) {
- // In order to prevent bilinear sampling at the of the crop rectangle we
- // may need to shrink it by 2 texels in each direction. Normally this
- // would just need to take 1/2 a texel off each end, but because the
- // chroma channels will likely be subsampled we need to chop off a whole
- // texel. This will cause artifacts if someone does nearest sampling
- // with 1:1 pixel:texel ratio, but it's impossible to simultaneously
- // accomodate the bilinear and nearest sampling uses.
- //
- // If nearest sampling turns out to be a desirable usage of these
- // textures then we could add the ability to switch a SurfaceTexture to
- // nearest-mode. Preferably, however, the image producers (video
- // decoder, camera, etc.) would simply not use a crop rectangle (or at
- // least not tell the framework about it) so that the GPU can do the
- // correct edge behavior.
- int xshrink = 0, yshrink = 0;
- if (mCurrentCrop.left > 0) {
- tx = float(mCurrentCrop.left + 1) / float(buf->getWidth());
- xshrink++;
- } else {
- tx = 0.0f;
- }
- if (mCurrentCrop.right < int32_t(buf->getWidth())) {
- xshrink++;
- }
- if (mCurrentCrop.bottom < int32_t(buf->getHeight())) {
- ty = (float(buf->getHeight() - mCurrentCrop.bottom) + 1.0f) /
- float(buf->getHeight());
- yshrink++;
- } else {
- ty = 0.0f;
- }
- if (mCurrentCrop.top > 0) {
- yshrink++;
- }
- sx = float(mCurrentCrop.width() - xshrink) / float(buf->getWidth());
- sy = float(mCurrentCrop.height() - yshrink) / float(buf->getHeight());
- } else {
- tx = 0.0f;
- ty = 0.0f;
- sx = 1.0f;
- sy = 1.0f;
- }
- float crop[16] = {
- sx, 0, 0, 0,
- 0, sy, 0, 0,
- 0, 0, 1, 0,
- tx, ty, 0, 1,
- };
-
- float mtxBeforeFlipV[16];
- mtxMul(mtxBeforeFlipV, crop, xform);
-
- // SurfaceFlinger expects the top of its window textures to be at a Y
- // coordinate of 0, so SurfaceTexture must behave the same way. We don't
- // want to expose this to applications, however, so we must add an
- // additional vertical flip to the transform after all the other transforms.
- mtxMul(mCurrentTransformMatrix, mtxFlipV, mtxBeforeFlipV);
-}
-
-nsecs_t SurfaceTexture::getTimestamp() {
- ST_LOGV("getTimestamp");
- Mutex::Autolock lock(mMutex);
- return mCurrentTimestamp;
-}
-
-void SurfaceTexture::setFrameAvailableListener(
- const sp<FrameAvailableListener>& listener) {
- ST_LOGV("setFrameAvailableListener");
- Mutex::Autolock lock(mMutex);
- mFrameAvailableListener = listener;
-}
-
-void SurfaceTexture::freeBufferLocked(int i) {
- mSlots[i].mGraphicBuffer = 0;
- mSlots[i].mBufferState = BufferSlot::FREE;
- mSlots[i].mFrameNumber = 0;
- if (mSlots[i].mEglImage != EGL_NO_IMAGE_KHR) {
- eglDestroyImageKHR(mSlots[i].mEglDisplay, mSlots[i].mEglImage);
- mSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
- mSlots[i].mEglDisplay = EGL_NO_DISPLAY;
- }
-}
-
-void SurfaceTexture::freeAllBuffersLocked() {
- LOGW_IF(!mQueue.isEmpty(),
- "freeAllBuffersLocked called but mQueue is not empty");
- mCurrentTexture = INVALID_BUFFER_SLOT;
- for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- freeBufferLocked(i);
- }
-}
-
-void SurfaceTexture::freeAllBuffersExceptHeadLocked() {
- LOGW_IF(!mQueue.isEmpty(),
- "freeAllBuffersExceptCurrentLocked called but mQueue is not empty");
- int head = -1;
- if (!mQueue.empty()) {
- Fifo::iterator front(mQueue.begin());
- head = *front;
- }
- mCurrentTexture = INVALID_BUFFER_SLOT;
- for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- if (i != head) {
- freeBufferLocked(i);
- }
- }
-}
-
-status_t SurfaceTexture::drainQueueLocked() {
- while (mSynchronousMode && !mQueue.isEmpty()) {
- mDequeueCondition.wait(mMutex);
- if (mAbandoned) {
- ST_LOGE("drainQueueLocked: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
- if (mConnectedApi == NO_CONNECTED_API) {
- ST_LOGE("drainQueueLocked: SurfaceTexture is not connected!");
- return NO_INIT;
- }
- }
- return NO_ERROR;
-}
-
-status_t SurfaceTexture::drainQueueAndFreeBuffersLocked() {
- status_t err = drainQueueLocked();
- if (err == NO_ERROR) {
- if (mSynchronousMode) {
- freeAllBuffersLocked();
- } else {
- freeAllBuffersExceptHeadLocked();
- }
- }
- return err;
-}
-
-EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy,
- const sp<GraphicBuffer>& graphicBuffer) {
- EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer();
- EGLint attrs[] = {
- EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
- EGL_NONE,
- };
- EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
- EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
- if (image == EGL_NO_IMAGE_KHR) {
- EGLint error = eglGetError();
- ST_LOGE("error creating EGLImage: %#x", error);
- }
- return image;
-}
-
-sp<GraphicBuffer> SurfaceTexture::getCurrentBuffer() const {
- Mutex::Autolock lock(mMutex);
- return mCurrentTextureBuf;
-}
-
-Rect SurfaceTexture::getCurrentCrop() const {
- Mutex::Autolock lock(mMutex);
- return mCurrentCrop;
-}
-
-uint32_t SurfaceTexture::getCurrentTransform() const {
- Mutex::Autolock lock(mMutex);
- return mCurrentTransform;
-}
-
-uint32_t SurfaceTexture::getCurrentScalingMode() const {
- Mutex::Autolock lock(mMutex);
- return mCurrentScalingMode;
-}
-
-bool SurfaceTexture::isSynchronousMode() const {
- Mutex::Autolock lock(mMutex);
- return mSynchronousMode;
-}
-
-int SurfaceTexture::query(int what, int* outValue)
-{
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("query: SurfaceTexture has been abandoned!");
- return NO_INIT;
- }
-
- int value;
- switch (what) {
- case NATIVE_WINDOW_WIDTH:
- value = mDefaultWidth;
- break;
- case NATIVE_WINDOW_HEIGHT:
- value = mDefaultHeight;
- break;
- case NATIVE_WINDOW_FORMAT:
- value = mPixelFormat;
- break;
- case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
- value = mSynchronousMode ?
- (MIN_UNDEQUEUED_BUFFERS-1) : MIN_UNDEQUEUED_BUFFERS;
- break;
- default:
- return BAD_VALUE;
- }
- outValue[0] = value;
- return NO_ERROR;
-}
-
-void SurfaceTexture::abandon() {
- Mutex::Autolock lock(mMutex);
- mQueue.clear();
- mAbandoned = true;
- mCurrentTextureBuf.clear();
- freeAllBuffersLocked();
- mDequeueCondition.signal();
-}
-
-void SurfaceTexture::setName(const String8& name) {
- mName = name;
-}
-
-void SurfaceTexture::dump(String8& result) const
-{
- char buffer[1024];
- dump(result, "", buffer, 1024);
-}
-
-void SurfaceTexture::dump(String8& result, const char* prefix,
- char* buffer, size_t SIZE) const
-{
- Mutex::Autolock _l(mMutex);
- snprintf(buffer, SIZE,
- "%smBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
- "mPixelFormat=%d, mTexName=%d\n",
- prefix, mBufferCount, mSynchronousMode, mDefaultWidth,
- mDefaultHeight, mPixelFormat, mTexName);
- result.append(buffer);
-
- String8 fifo;
- int fifoSize = 0;
- Fifo::const_iterator i(mQueue.begin());
- while (i != mQueue.end()) {
- snprintf(buffer, SIZE, "%02d ", *i++);
- fifoSize++;
- fifo.append(buffer);
- }
-
- snprintf(buffer, SIZE,
- "%scurrent: {crop=[%d,%d,%d,%d], transform=0x%02x, current=%d}\n"
- "%snext : {crop=[%d,%d,%d,%d], transform=0x%02x, FIFO(%d)={%s}}\n"
- ,
- prefix, mCurrentCrop.left,
- mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
- mCurrentTransform, mCurrentTexture,
- prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right,
- mNextCrop.bottom, mNextTransform, fifoSize, fifo.string()
- );
- result.append(buffer);
-
- struct {
- const char * operator()(int state) const {
- switch (state) {
- case BufferSlot::DEQUEUED: return "DEQUEUED";
- case BufferSlot::QUEUED: return "QUEUED";
- case BufferSlot::FREE: return "FREE";
- default: return "Unknown";
- }
- }
- } stateName;
-
- for (int i=0 ; i<mBufferCount ; i++) {
- const BufferSlot& slot(mSlots[i]);
- snprintf(buffer, SIZE,
- "%s%s[%02d] "
- "state=%-8s, crop=[%d,%d,%d,%d], "
- "transform=0x%02x, timestamp=%lld",
- prefix, (i==mCurrentTexture)?">":" ", i,
- stateName(slot.mBufferState),
- slot.mCrop.left, slot.mCrop.top, slot.mCrop.right,
- slot.mCrop.bottom, slot.mTransform, slot.mTimestamp
- );
- result.append(buffer);
-
- const sp<GraphicBuffer>& buf(slot.mGraphicBuffer);
- if (buf != NULL) {
- snprintf(buffer, SIZE,
- ", %p [%4ux%4u:%4u,%3X]",
- buf->handle, buf->width, buf->height, buf->stride,
- buf->format);
- result.append(buffer);
- }
- result.append("\n");
- }
-}
-
-static void mtxMul(float out[16], const float a[16], const float b[16]) {
- out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
- out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
- out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
- out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];
-
- out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
- out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
- out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
- out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];
-
- out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
- out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
- out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
- out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];
-
- out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
- out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
- out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
- out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
-}
-
-}; // namespace android
diff --git a/src/imports/nativemedia/SurfaceTexture_4_0.h b/src/imports/nativemedia/SurfaceTexture_4_0.h
deleted file mode 100644
index 53cc852..0000000
--- a/src/imports/nativemedia/SurfaceTexture_4_0.h
+++ /dev/null
@@ -1,517 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_GUI_SURFACETEXTURE_H
-#define ANDROID_GUI_SURFACETEXTURE_H
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
-#include <gui/ISurfaceTexture.h>
-
-#include <ui/GraphicBuffer.h>
-
-#include <utils/String8.h>
-#include <utils/Vector.h>
-#include <utils/threads.h>
-
-#define ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID "mSurfaceTexture"
-
-namespace android {
-// ----------------------------------------------------------------------------
-
-class IGraphicBufferAlloc;
-class String8;
-
-class SurfaceTexture : public BnSurfaceTexture {
-public:
- enum { MIN_UNDEQUEUED_BUFFERS = 2 };
- enum {
- MIN_ASYNC_BUFFER_SLOTS = MIN_UNDEQUEUED_BUFFERS + 1,
- MIN_SYNC_BUFFER_SLOTS = MIN_UNDEQUEUED_BUFFERS
- };
- enum { NUM_BUFFER_SLOTS = 32 };
- enum { NO_CONNECTED_API = 0 };
-
- struct FrameAvailableListener : public virtual RefBase {
- // onFrameAvailable() is called from queueBuffer() each time an
- // additional frame becomes available for consumption. This means that
- // frames that are queued while in asynchronous mode only trigger the
- // callback if no previous frames are pending. Frames queued while in
- // synchronous mode always trigger the callback.
- //
- // This is called without any lock held and can be called concurrently
- // by multiple threads.
- virtual void onFrameAvailable() = 0;
- };
-
- // SurfaceTexture constructs a new SurfaceTexture object. tex indicates the
- // name of the OpenGL ES texture to which images are to be streamed. This
- // texture name cannot be changed once the SurfaceTexture is created.
- // allowSynchronousMode specifies whether or not synchronous mode can be
- // enabled. texTarget specifies the OpenGL ES texture target to which the
- // texture will be bound in updateTexImage. useFenceSync specifies whether
- // fences should be used to synchronize access to buffers if that behavior
- // is enabled at compile-time.
- SurfaceTexture(GLuint tex, bool allowSynchronousMode = true,
- GLenum texTarget = GL_TEXTURE_EXTERNAL_OES, bool useFenceSync = true);
-
- virtual ~SurfaceTexture();
-
- // setBufferCount updates the number of available buffer slots. After
- // calling this all buffer slots are both unallocated and owned by the
- // SurfaceTexture object (i.e. they are not owned by the client).
- virtual status_t setBufferCount(int bufferCount);
-
- virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);
-
- // dequeueBuffer gets the next buffer slot index for the client to use. If a
- // buffer slot is available then that slot index is written to the location
- // pointed to by the buf argument and a status of OK is returned. If no
- // slot is available then a status of -EBUSY is returned and buf is
- // unmodified.
- // The width and height parameters must be no greater than the minimum of
- // GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv).
- // An error due to invalid dimensions might not be reported until
- // updateTexImage() is called.
- virtual status_t dequeueBuffer(int *buf, uint32_t width, uint32_t height,
- uint32_t format, uint32_t usage);
-
- // queueBuffer returns a filled buffer to the SurfaceTexture. In addition, a
- // timestamp must be provided for the buffer. The timestamp is in
- // nanoseconds, and must be monotonically increasing. Its other semantics
- // (zero point, etc) are client-dependent and should be documented by the
- // client.
- virtual status_t queueBuffer(int buf, int64_t timestamp,
- uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform);
- virtual void cancelBuffer(int buf);
- virtual status_t setCrop(const Rect& reg);
- virtual status_t setTransform(uint32_t transform);
- virtual status_t setScalingMode(int mode);
-
- virtual int query(int what, int* value);
-
- // setSynchronousMode set whether dequeueBuffer is synchronous or
- // asynchronous. In synchronous mode, dequeueBuffer blocks until
- // a buffer is available, the currently bound buffer can be dequeued and
- // queued buffers will be retired in order.
- // The default mode is asynchronous.
- virtual status_t setSynchronousMode(bool enabled);
-
- // connect attempts to connect a client API to the SurfaceTexture. This
- // must be called before any other ISurfaceTexture methods are called except
- // for getAllocator.
- //
- // This method will fail if the connect was previously called on the
- // SurfaceTexture and no corresponding disconnect call was made.
- virtual status_t connect(int api,
- uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform);
-
- // disconnect attempts to disconnect a client API from the SurfaceTexture.
- // Calling this method will cause any subsequent calls to other
- // ISurfaceTexture methods to fail except for getAllocator and connect.
- // Successfully calling connect after this will allow the other methods to
- // succeed again.
- //
- // This method will fail if the the SurfaceTexture is not currently
- // connected to the specified client API.
- virtual status_t disconnect(int api);
-
- // updateTexImage sets the image contents of the target texture to that of
- // the most recently queued buffer.
- //
- // This call may only be made while the OpenGL ES context to which the
- // target texture belongs is bound to the calling thread.
- status_t updateTexImage();
-
- // setBufferCountServer set the buffer count. If the client has requested
- // a buffer count using setBufferCount, the server-buffer count will
- // take effect once the client sets the count back to zero.
- status_t setBufferCountServer(int bufferCount);
-
- // getTransformMatrix retrieves the 4x4 texture coordinate transform matrix
- // associated with the texture image set by the most recent call to
- // updateTexImage.
- //
- // This transform matrix maps 2D homogeneous texture coordinates of the form
- // (s, t, 0, 1) with s and t in the inclusive range [0, 1] to the texture
- // coordinate that should be used to sample that location from the texture.
- // Sampling the texture outside of the range of this transform is undefined.
- //
- // This transform is necessary to compensate for transforms that the stream
- // content producer may implicitly apply to the content. By forcing users of
- // a SurfaceTexture to apply this transform we avoid performing an extra
- // copy of the data that would be needed to hide the transform from the
- // user.
- //
- // The matrix is stored in column-major order so that it may be passed
- // directly to OpenGL ES via the glLoadMatrixf or glUniformMatrix4fv
- // functions.
- void getTransformMatrix(float mtx[16]);
-
- // getTimestamp retrieves the timestamp associated with the texture image
- // set by the most recent call to updateTexImage.
- //
- // The timestamp is in nanoseconds, and is monotonically increasing. Its
- // other semantics (zero point, etc) are source-dependent and should be
- // documented by the source.
- int64_t getTimestamp();
-
- // setFrameAvailableListener sets the listener object that will be notified
- // when a new frame becomes available.
- void setFrameAvailableListener(const sp<FrameAvailableListener>& listener);
-
- // getAllocator retrieves the binder object that must be referenced as long
- // as the GraphicBuffers dequeued from this SurfaceTexture are referenced.
- // Holding this binder reference prevents SurfaceFlinger from freeing the
- // buffers before the client is done with them.
- sp<IBinder> getAllocator();
-
- // setDefaultBufferSize is used to set the size of buffers returned by
- // requestBuffers when a with and height of zero is requested.
- // A call to setDefaultBufferSize() may trigger requestBuffers() to
- // be called from the client.
- // The width and height parameters must be no greater than the minimum of
- // GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv).
- // An error due to invalid dimensions might not be reported until
- // updateTexImage() is called.
- status_t setDefaultBufferSize(uint32_t width, uint32_t height);
-
- // getCurrentBuffer returns the buffer associated with the current image.
- sp<GraphicBuffer> getCurrentBuffer() const;
-
- // getCurrentTextureTarget returns the texture target of the current
- // texture as returned by updateTexImage().
- GLenum getCurrentTextureTarget() const;
-
- // getCurrentCrop returns the cropping rectangle of the current buffer
- Rect getCurrentCrop() const;
-
- // getCurrentTransform returns the transform of the current buffer
- uint32_t getCurrentTransform() const;
-
- // getCurrentScalingMode returns the scaling mode of the current buffer
- uint32_t getCurrentScalingMode() const;
-
- // isSynchronousMode returns whether the SurfaceTexture is currently in
- // synchronous mode.
- bool isSynchronousMode() const;
-
- // abandon frees all the buffers and puts the SurfaceTexture into the
- // 'abandoned' state. Once put in this state the SurfaceTexture can never
- // leave it. When in the 'abandoned' state, all methods of the
- // ISurfaceTexture interface will fail with the NO_INIT error.
- //
- // Note that while calling this method causes all the buffers to be freed
- // from the perspective of the the SurfaceTexture, if there are additional
- // references on the buffers (e.g. if a buffer is referenced by a client or
- // by OpenGL ES as a texture) then those buffer will remain allocated.
- void abandon();
-
- // set the name of the SurfaceTexture that will be used to identify it in
- // log messages.
- void setName(const String8& name);
-
- // dump our state in a String
- void dump(String8& result) const;
- void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const;
-
-protected:
-
- // freeBufferLocked frees the resources (both GraphicBuffer and EGLImage)
- // for the given slot.
- void freeBufferLocked(int index);
-
- // freeAllBuffersLocked frees the resources (both GraphicBuffer and
- // EGLImage) for all slots.
- void freeAllBuffersLocked();
-
- // freeAllBuffersExceptHeadLocked frees the resources (both GraphicBuffer
- // and EGLImage) for all slots except the head of mQueue
- void freeAllBuffersExceptHeadLocked();
-
- // drainQueueLocked drains the buffer queue if we're in synchronous mode
- // returns immediately otherwise. return NO_INIT if SurfaceTexture
- // became abandoned or disconnected during this call.
- status_t drainQueueLocked();
-
- // drainQueueAndFreeBuffersLocked drains the buffer queue if we're in
- // synchronous mode and free all buffers. In asynchronous mode, all buffers
- // are freed except the current buffer.
- status_t drainQueueAndFreeBuffersLocked();
-
- static bool isExternalFormat(uint32_t format);
-
-private:
-
- // createImage creates a new EGLImage from a GraphicBuffer.
- EGLImageKHR createImage(EGLDisplay dpy,
- const sp<GraphicBuffer>& graphicBuffer);
-
- status_t setBufferCountServerLocked(int bufferCount);
-
- // computeCurrentTransformMatrix computes the transform matrix for the
- // current texture. It uses mCurrentTransform and the current GraphicBuffer
- // to compute this matrix and stores it in mCurrentTransformMatrix.
- void computeCurrentTransformMatrix();
-
- enum { INVALID_BUFFER_SLOT = -1 };
-
- struct BufferSlot {
-
- BufferSlot()
- : mEglImage(EGL_NO_IMAGE_KHR),
- mEglDisplay(EGL_NO_DISPLAY),
- mBufferState(BufferSlot::FREE),
- mRequestBufferCalled(false),
- mTransform(0),
- mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
- mTimestamp(0),
- mFrameNumber(0),
- mFence(EGL_NO_SYNC_KHR) {
- mCrop.makeInvalid();
- }
-
- // mGraphicBuffer points to the buffer allocated for this slot or is NULL
- // if no buffer has been allocated.
- sp<GraphicBuffer> mGraphicBuffer;
-
- // mEglImage is the EGLImage created from mGraphicBuffer.
- EGLImageKHR mEglImage;
-
- // mEglDisplay is the EGLDisplay used to create mEglImage.
- EGLDisplay mEglDisplay;
-
- // BufferState represents the different states in which a buffer slot
- // can be.
- enum BufferState {
- // FREE indicates that the buffer is not currently being used and
- // will not be used in the future until it gets dequeued and
- // subsequently queued by the client.
- FREE = 0,
-
- // DEQUEUED indicates that the buffer has been dequeued by the
- // client, but has not yet been queued or canceled. The buffer is
- // considered 'owned' by the client, and the server should not use
- // it for anything.
- //
- // Note that when in synchronous-mode (mSynchronousMode == true),
- // the buffer that's currently attached to the texture may be
- // dequeued by the client. That means that the current buffer can
- // be in either the DEQUEUED or QUEUED state. In asynchronous mode,
- // however, the current buffer is always in the QUEUED state.
- DEQUEUED = 1,
-
- // QUEUED indicates that the buffer has been queued by the client,
- // and has not since been made available for the client to dequeue.
- // Attaching the buffer to the texture does NOT transition the
- // buffer away from the QUEUED state. However, in Synchronous mode
- // the current buffer may be dequeued by the client under some
- // circumstances. See the note about the current buffer in the
- // documentation for DEQUEUED.
- QUEUED = 2,
- };
-
- // mBufferState is the current state of this buffer slot.
- BufferState mBufferState;
-
- // mRequestBufferCalled is used for validating that the client did
- // call requestBuffer() when told to do so. Technically this is not
- // needed but useful for debugging and catching client bugs.
- bool mRequestBufferCalled;
-
- // mCrop is the current crop rectangle for this buffer slot. This gets
- // set to mNextCrop each time queueBuffer gets called for this buffer.
- Rect mCrop;
-
- // mTransform is the current transform flags for this buffer slot. This
- // gets set to mNextTransform each time queueBuffer gets called for this
- // slot.
- uint32_t mTransform;
-
- // mScalingMode is the current scaling mode for this buffer slot. This
- // gets set to mNextScalingMode each time queueBuffer gets called for
- // this slot.
- uint32_t mScalingMode;
-
- // mTimestamp is the current timestamp for this buffer slot. This gets
- // to set by queueBuffer each time this slot is queued.
- int64_t mTimestamp;
-
- // mFrameNumber is the number of the queued frame for this slot.
- uint64_t mFrameNumber;
-
- // mFence is the EGL sync object that must signal before the buffer
- // associated with this buffer slot may be dequeued. It is initialized
- // to EGL_NO_SYNC_KHR when the buffer is created and (optionally, based
- // on a compile-time option) set to a new sync object in updateTexImage.
- EGLSyncKHR mFence;
- };
-
- // mSlots is the array of buffer slots that must be mirrored on the client
- // side. This allows buffer ownership to be transferred between the client
- // and server without sending a GraphicBuffer over binder. The entire array
- // is initialized to NULL at construction time, and buffers are allocated
- // for a slot when requestBuffer is called with that slot's index.
- BufferSlot mSlots[NUM_BUFFER_SLOTS];
-
- // mDefaultWidth holds the default width of allocated buffers. It is used
- // in requestBuffers() if a width and height of zero is specified.
- uint32_t mDefaultWidth;
-
- // mDefaultHeight holds the default height of allocated buffers. It is used
- // in requestBuffers() if a width and height of zero is specified.
- uint32_t mDefaultHeight;
-
- // mPixelFormat holds the pixel format of allocated buffers. It is used
- // in requestBuffers() if a format of zero is specified.
- uint32_t mPixelFormat;
-
- // mBufferCount is the number of buffer slots that the client and server
- // must maintain. It defaults to MIN_ASYNC_BUFFER_SLOTS and can be changed
- // by calling setBufferCount or setBufferCountServer
- int mBufferCount;
-
- // mClientBufferCount is the number of buffer slots requested by the client.
- // The default is zero, which means the client doesn't care how many buffers
- // there is.
- int mClientBufferCount;
-
- // mServerBufferCount buffer count requested by the server-side
- int mServerBufferCount;
-
- // mCurrentTexture is the buffer slot index of the buffer that is currently
- // bound to the OpenGL texture. It is initialized to INVALID_BUFFER_SLOT,
- // indicating that no buffer slot is currently bound to the texture. Note,
- // however, that a value of INVALID_BUFFER_SLOT does not necessarily mean
- // that no buffer is bound to the texture. A call to setBufferCount will
- // reset mCurrentTexture to INVALID_BUFFER_SLOT.
- int mCurrentTexture;
-
- // mCurrentTextureBuf is the graphic buffer of the current texture. It's
- // possible that this buffer is not associated with any buffer slot, so we
- // must track it separately in order to support the getCurrentBuffer method.
- sp<GraphicBuffer> mCurrentTextureBuf;
-
- // mCurrentCrop is the crop rectangle that applies to the current texture.
- // It gets set each time updateTexImage is called.
- Rect mCurrentCrop;
-
- // mCurrentTransform is the transform identifier for the current texture. It
- // gets set each time updateTexImage is called.
- uint32_t mCurrentTransform;
-
- // mCurrentScalingMode is the scaling mode for the current texture. It gets
- // set to each time updateTexImage is called.
- uint32_t mCurrentScalingMode;
-
- // mCurrentTransformMatrix is the transform matrix for the current texture.
- // It gets computed by computeTransformMatrix each time updateTexImage is
- // called.
- float mCurrentTransformMatrix[16];
-
- // mCurrentTimestamp is the timestamp for the current texture. It
- // gets set each time updateTexImage is called.
- int64_t mCurrentTimestamp;
-
- // mNextCrop is the crop rectangle that will be used for the next buffer
- // that gets queued. It is set by calling setCrop.
- Rect mNextCrop;
-
- // mNextTransform is the transform identifier that will be used for the next
- // buffer that gets queued. It is set by calling setTransform.
- uint32_t mNextTransform;
-
- // mNextScalingMode is the scaling mode that will be used for the next
- // buffers that get queued. It is set by calling setScalingMode.
- int mNextScalingMode;
-
- // mTexName is the name of the OpenGL texture to which streamed images will
- // be bound when updateTexImage is called. It is set at construction time
- // changed with a call to setTexName.
- const GLuint mTexName;
-
- // mGraphicBufferAlloc is the connection to SurfaceFlinger that is used to
- // allocate new GraphicBuffer objects.
- //sp<IGraphicBufferAlloc> mGraphicBufferAlloc;
-
- // mFrameAvailableListener is the listener object that will be called when a
- // new frame becomes available. If it is not NULL it will be called from
- // queueBuffer.
- sp<FrameAvailableListener> mFrameAvailableListener;
-
- // mSynchronousMode whether we're in synchronous mode or not
- bool mSynchronousMode;
-
- // mAllowSynchronousMode whether we allow synchronous mode or not
- const bool mAllowSynchronousMode;
-
- // mConnectedApi indicates the API that is currently connected to this
- // SurfaceTexture. It defaults to NO_CONNECTED_API (= 0), and gets updated
- // by the connect and disconnect methods.
- int mConnectedApi;
-
- // mDequeueCondition condition used for dequeueBuffer in synchronous mode
- mutable Condition mDequeueCondition;
-
- // mQueue is a FIFO of queued buffers used in synchronous mode
- typedef Vector<int> Fifo;
- Fifo mQueue;
-
- // mAbandoned indicates that the SurfaceTexture will no longer be used to
- // consume images buffers pushed to it using the ISurfaceTexture interface.
- // It is initialized to false, and set to true in the abandon method. A
- // SurfaceTexture that has been abandoned will return the NO_INIT error from
- // all ISurfaceTexture methods capable of returning an error.
- bool mAbandoned;
-
- // mName is a string used to identify the SurfaceTexture in log messages.
- // It is set by the setName method.
- String8 mName;
-
- // mUseFenceSync indicates whether creation of the EGL_KHR_fence_sync
- // extension should be used to prevent buffers from being dequeued before
- // it's safe for them to be written. It gets set at construction time and
- // never changes.
- const bool mUseFenceSync;
-
- // mMutex is the mutex used to prevent concurrent access to the member
- // variables of SurfaceTexture objects. It must be locked whenever the
- // member variables are accessed.
- mutable Mutex mMutex;
-
- // mTexTarget is the GL texture target with which the GL texture object is
- // associated. It is set in the constructor and never changed. It is
- // almost always GL_TEXTURE_EXTERNAL_OES except for one use case in Android
- // Browser. In that case it is set to GL_TEXTURE_2D to allow
- // glCopyTexSubImage to read from the texture. This is a hack to work
- // around a GL driver limitation on the number of FBO attachments, which the
- // browser's tile cache exceeds.
- const GLenum mTexTarget;
-
- // mFrameCounter is the free running counter, incremented for every buffer queued
- // with the surface Texture.
- uint64_t mFrameCounter;
-
-
-};
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_GUI_SURFACETEXTURE_H
diff --git a/src/imports/nativemedia/SurfaceTexture_4_1.cpp b/src/imports/nativemedia/SurfaceTexture_4_1.cpp
deleted file mode 100644
index 9f8fd84..0000000
--- a/src/imports/nativemedia/SurfaceTexture_4_1.cpp
+++ /dev/null
@@ -1,866 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "SurfaceTexture"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-//#define LOG_NDEBUG 0
-
-#define GL_GLEXT_PROTOTYPES
-#define EGL_EGLEXT_PROTOTYPES
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
-#include <QtDebug>
-
-#include <hardware/hardware.h>
-
-#include <gui/IGraphicBufferAlloc.h>
-#include <gui/ISurfaceComposer.h>
-#include <gui/SurfaceComposerClient.h>
-#include <SurfaceTexture.h>
-
-#include <private/gui/ComposerService.h>
-
-#include <utils/Log.h>
-#include <utils/String8.h>
-#include <utils/Trace.h>
-
-// This compile option makes SurfaceTexture use the EGL_KHR_fence_sync extension
-// to synchronize access to the buffers. It will cause dequeueBuffer to stall,
-// waiting for the GL reads for the buffer being dequeued to complete before
-// allowing the buffer to be dequeued.
-#ifdef USE_FENCE_SYNC
-#ifdef ALLOW_DEQUEUE_CURRENT_BUFFER
-#error "USE_FENCE_SYNC and ALLOW_DEQUEUE_CURRENT_BUFFER are incompatible"
-#endif
-#endif
-
-// Macros for including the SurfaceTexture name in log messages
-#define ST_LOGV(x, ...) qDebug("[V/%s] "x, mName.string(), ##__VA_ARGS__)
-#define ST_LOGD(x, ...) qDebug("[D/%s] "x, mName.string(), ##__VA_ARGS__)
-#define ST_LOGI(x, ...) qDebug("[I/%s] "x, mName.string(), ##__VA_ARGS__)
-#define ST_LOGW(x, ...) qDebug("[W/%s] "x, mName.string(), ##__VA_ARGS__)
-#define ST_LOGE(x, ...) qDebug("[E/%s] "x, mName.string(), ##__VA_ARGS__)
-
-namespace android {
-
-// Transform matrices
-static float mtxIdentity[16] = {
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1,
-};
-static float mtxFlipH[16] = {
- -1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 1, 0, 0, 1,
-};
-static float mtxFlipV[16] = {
- 1, 0, 0, 0,
- 0, -1, 0, 0,
- 0, 0, 1, 0,
- 0, 1, 0, 1,
-};
-static float mtxRot90[16] = {
- 0, 1, 0, 0,
- -1, 0, 0, 0,
- 0, 0, 1, 0,
- 1, 0, 0, 1,
-};
-static float mtxRot180[16] = {
- -1, 0, 0, 0,
- 0, -1, 0, 0,
- 0, 0, 1, 0,
- 1, 1, 0, 1,
-};
-static float mtxRot270[16] = {
- 0, -1, 0, 0,
- 1, 0, 0, 0,
- 0, 0, 1, 0,
- 0, 1, 0, 1,
-};
-
-static void mtxMul(float out[16], const float a[16], const float b[16]);
-
-// Get an ID that's unique within this process.
-static int32_t createProcessUniqueId() {
- static volatile int32_t globalCounter = 0;
- return android_atomic_inc(&globalCounter);
-}
-
-SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode,
- GLenum texTarget, bool useFenceSync, const sp<BufferQueue> &bufferQueue) :
- mCurrentTransform(0),
- mCurrentTimestamp(0),
- mFilteringEnabled(true),
- mTexName(tex),
-#ifdef USE_FENCE_SYNC
- mUseFenceSync(useFenceSync),
-#else
- mUseFenceSync(false),
-#endif
- mTexTarget(texTarget),
- mEglDisplay(EGL_NO_DISPLAY),
- mEglContext(EGL_NO_CONTEXT),
- mAbandoned(false),
- mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT),
- mAttached(true)
-{
- // Choose a name using the PID and a process-unique ID.
- mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
- ST_LOGV("SurfaceTexture");
- if (bufferQueue == 0) {
- ST_LOGV("Creating a new BufferQueue");
- mBufferQueue = new BufferQueue(allowSynchronousMode);
- }
- else {
- mBufferQueue = bufferQueue;
- }
-
- memcpy(mCurrentTransformMatrix, mtxIdentity,
- sizeof(mCurrentTransformMatrix));
-
- // Note that we can't create an sp<...>(this) in a ctor that will not keep a
- // reference once the ctor ends, as that would cause the refcount of 'this'
- // dropping to 0 at the end of the ctor. Since all we need is a wp<...>
- // that's what we create.
- wp<BufferQueue::ConsumerListener> listener;
- sp<BufferQueue::ConsumerListener> proxy;
- listener = static_cast<BufferQueue::ConsumerListener*>(this);
- proxy = new BufferQueue::ProxyConsumerListener(listener);
-
- status_t err = mBufferQueue->consumerConnect(proxy);
- if (err != NO_ERROR) {
- ST_LOGE("SurfaceTexture: error connecting to BufferQueue: %s (%d)",
- strerror(-err), err);
- } else {
- mBufferQueue->setConsumerName(mName);
- mBufferQueue->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
- }
-}
-
-SurfaceTexture::~SurfaceTexture() {
- ST_LOGV("~SurfaceTexture");
-
- abandon();
-}
-
-status_t SurfaceTexture::setBufferCountServer(int bufferCount) {
- Mutex::Autolock lock(mMutex);
- return mBufferQueue->setBufferCountServer(bufferCount);
-}
-
-
-status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h)
-{
- Mutex::Autolock lock(mMutex);
- mDefaultWidth = w;
- mDefaultHeight = h;
- return mBufferQueue->setDefaultBufferSize(w, h);
-}
-
-status_t SurfaceTexture::updateTexImage() {
- return SurfaceTexture::updateTexImage(NULL);
-}
-
-status_t SurfaceTexture::updateTexImage(BufferRejecter* rejecter) {
- ATRACE_CALL();
- ST_LOGV("updateTexImage");
- Mutex::Autolock lock(mMutex);
-
- status_t err = NO_ERROR;
-
- if (mAbandoned) {
- ST_LOGE("updateTexImage: SurfaceTexture is abandoned!");
- return NO_INIT;
- }
-
- if (!mAttached) {
- ST_LOGE("updateTexImage: SurfaceTexture is not attached to an OpenGL "
- "ES context");
- return INVALID_OPERATION;
- }
-
- EGLDisplay dpy = eglGetCurrentDisplay();
- EGLContext ctx = eglGetCurrentContext();
-
- if ((mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) ||
- dpy == EGL_NO_DISPLAY) {
- ST_LOGE("updateTexImage: invalid current EGLDisplay");
- return INVALID_OPERATION;
- }
-
- if ((mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) ||
- ctx == EGL_NO_CONTEXT) {
- ST_LOGE("updateTexImage: invalid current EGLContext");
- return INVALID_OPERATION;
- }
-
- mEglDisplay = dpy;
- mEglContext = ctx;
-
- BufferQueue::BufferItem item;
-
- // In asynchronous mode the list is guaranteed to be one buffer
- // deep, while in synchronous mode we use the oldest buffer.
- err = mBufferQueue->acquireBuffer(&item);
- if (err == NO_ERROR) {
- int buf = item.mBuf;
- // This buffer was newly allocated, so we need to clean up on our side
- if (item.mGraphicBuffer != NULL) {
- mEGLSlots[buf].mGraphicBuffer = 0;
- if (mEGLSlots[buf].mEglImage != EGL_NO_IMAGE_KHR) {
- eglDestroyImageKHR(dpy, mEGLSlots[buf].mEglImage);
- mEGLSlots[buf].mEglImage = EGL_NO_IMAGE_KHR;
- }
- mEGLSlots[buf].mGraphicBuffer = item.mGraphicBuffer;
- }
-
- // we call the rejecter here, in case the caller has a reason to
- // not accept this buffer. this is used by SurfaceFlinger to
- // reject buffers which have the wrong size
- if (rejecter && rejecter->reject(mEGLSlots[buf].mGraphicBuffer, item)) {
- mBufferQueue->releaseBuffer(buf, dpy, mEGLSlots[buf].mFence);
- mEGLSlots[buf].mFence = EGL_NO_SYNC_KHR;
- glBindTexture(mTexTarget, mTexName);
- return NO_ERROR;
- }
-
- // Update the GL texture object. We may have to do this even when
- // item.mGraphicBuffer == NULL, if we destroyed the EGLImage when
- // detaching from a context but the buffer has not been re-allocated.
- EGLImageKHR image = mEGLSlots[buf].mEglImage;
- if (image == EGL_NO_IMAGE_KHR) {
- if (mEGLSlots[buf].mGraphicBuffer == NULL) {
- ST_LOGE("updateTexImage: buffer at slot %d is null", buf);
- err = BAD_VALUE;
- } else {
- image = createImage(dpy, mEGLSlots[buf].mGraphicBuffer);
- mEGLSlots[buf].mEglImage = image;
- if (image == EGL_NO_IMAGE_KHR) {
- // NOTE: if dpy was invalid, createImage() is guaranteed to
- // fail. so we'd end up here.
- err = UNKNOWN_ERROR;
- }
- }
- }
-
- if (err == NO_ERROR) {
- GLint error;
- while ((error = glGetError()) != GL_NO_ERROR) {
- ST_LOGW("updateTexImage: clearing GL error: %#04x", error);
- }
-
- glBindTexture(mTexTarget, mTexName);
- glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
-
- while ((error = glGetError()) != GL_NO_ERROR) {
- ST_LOGE("updateTexImage: error binding external texture image %p "
- "(slot %d): %#04x", image, buf, error);
- err = UNKNOWN_ERROR;
- }
-
- if (err == NO_ERROR) {
- err = syncForReleaseLocked(dpy);
- }
- }
-
- if (err != NO_ERROR) {
- // Release the buffer we just acquired. It's not safe to
- // release the old buffer, so instead we just drop the new frame.
- mBufferQueue->releaseBuffer(buf, dpy, mEGLSlots[buf].mFence);
- mEGLSlots[buf].mFence = EGL_NO_SYNC_KHR;
- return err;
- }
-
- ST_LOGV("updateTexImage: (slot=%d buf=%p) -> (slot=%d buf=%p)",
- mCurrentTexture,
- mCurrentTextureBuf != NULL ? mCurrentTextureBuf->handle : 0,
- buf, item.mGraphicBuffer != NULL ? item.mGraphicBuffer->handle : 0);
-
- // release old buffer
- if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
- status_t status = mBufferQueue->releaseBuffer(mCurrentTexture, dpy,
- mEGLSlots[mCurrentTexture].mFence);
-
- mEGLSlots[mCurrentTexture].mFence = EGL_NO_SYNC_KHR;
- if (status == BufferQueue::STALE_BUFFER_SLOT) {
- freeBufferLocked(mCurrentTexture);
- } else if (status != NO_ERROR) {
- ST_LOGE("updateTexImage: released invalid buffer");
- err = status;
- }
- }
-
- // Update the SurfaceTexture state.
- mCurrentTexture = buf;
- mCurrentTextureBuf = mEGLSlots[buf].mGraphicBuffer;
- mCurrentCrop = item.mCrop;
- mCurrentTransform = item.mTransform;
- mCurrentScalingMode = item.mScalingMode;
- mCurrentTimestamp = item.mTimestamp;
- computeCurrentTransformMatrix();
- } else {
- if (err < 0) {
- ALOGE("updateTexImage failed on acquire %d", err);
- }
- // We always bind the texture even if we don't update its contents.
- glBindTexture(mTexTarget, mTexName);
- return OK;
- }
-
- return err;
-}
-
-status_t SurfaceTexture::detachFromContext() {
- ATRACE_CALL();
- ST_LOGV("detachFromContext");
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("detachFromContext: abandoned SurfaceTexture");
- return NO_INIT;
- }
-
- if (!mAttached) {
- ST_LOGE("detachFromContext: SurfaceTexture is not attached to a "
- "context");
- return INVALID_OPERATION;
- }
-
- EGLDisplay dpy = eglGetCurrentDisplay();
- EGLContext ctx = eglGetCurrentContext();
-
- if (mEglDisplay != dpy && mEglDisplay != EGL_NO_DISPLAY) {
- ST_LOGE("detachFromContext: invalid current EGLDisplay");
- return INVALID_OPERATION;
- }
-
- if (mEglContext != ctx && mEglContext != EGL_NO_CONTEXT) {
- ST_LOGE("detachFromContext: invalid current EGLContext");
- return INVALID_OPERATION;
- }
-
- if (dpy != EGL_NO_DISPLAY && ctx != EGL_NO_CONTEXT) {
- status_t err = syncForReleaseLocked(dpy);
- if (err != OK) {
- return err;
- }
-
- glDeleteTextures(1, &mTexName);
- }
-
- // Because we're giving up the EGLDisplay we need to free all the EGLImages
- // that are associated with it. They'll be recreated when the
- // SurfaceTexture gets attached to a new OpenGL ES context (and thus gets a
- // new EGLDisplay).
- for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
- EGLImageKHR img = mEGLSlots[i].mEglImage;
- if (img != EGL_NO_IMAGE_KHR) {
- eglDestroyImageKHR(mEglDisplay, img);
- mEGLSlots[i].mEglImage = EGL_NO_IMAGE_KHR;
- }
- }
-
- mEglDisplay = EGL_NO_DISPLAY;
- mEglContext = EGL_NO_CONTEXT;
- mAttached = false;
-
- return OK;
-}
-
-status_t SurfaceTexture::attachToContext(GLuint tex) {
- ATRACE_CALL();
- ST_LOGV("attachToContext");
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- ST_LOGE("attachToContext: abandoned SurfaceTexture");
- return NO_INIT;
- }
-
- if (mAttached) {
- ST_LOGE("attachToContext: SurfaceTexture is already attached to a "
- "context");
- return INVALID_OPERATION;
- }
-
- EGLDisplay dpy = eglGetCurrentDisplay();
- EGLContext ctx = eglGetCurrentContext();
-
- if (dpy == EGL_NO_DISPLAY) {
- ST_LOGE("attachToContext: invalid current EGLDisplay");
- return INVALID_OPERATION;
- }
-
- if (ctx == EGL_NO_CONTEXT) {
- ST_LOGE("attachToContext: invalid current EGLContext");
- return INVALID_OPERATION;
- }
-
- // We need to bind the texture regardless of whether there's a current
- // buffer.
- glBindTexture(mTexTarget, tex);
-
- if (mCurrentTextureBuf != NULL) {
- // The EGLImageKHR that was associated with the slot was destroyed when
- // the SurfaceTexture was detached from the old context, so we need to
- // recreate it here.
- EGLImageKHR image = createImage(dpy, mCurrentTextureBuf);
- if (image == EGL_NO_IMAGE_KHR) {
- return UNKNOWN_ERROR;
- }
-
- // Attach the current buffer to the GL texture.
- glEGLImageTargetTexture2DOES(mTexTarget, (GLeglImageOES)image);
-
- GLint error;
- status_t err = OK;
- while ((error = glGetError()) != GL_NO_ERROR) {
- ST_LOGE("attachToContext: error binding external texture image %p "
- "(slot %d): %#04x", image, mCurrentTexture, error);
- err = UNKNOWN_ERROR;
- }
-
- // We destroy the EGLImageKHR here because the current buffer may no
- // longer be associated with one of the buffer slots, so we have
- // nowhere to to store it. If the buffer is still associated with a
- // slot then another EGLImageKHR will be created next time that buffer
- // gets acquired in updateTexImage.
- eglDestroyImageKHR(dpy, image);
-
- if (err != OK) {
- return err;
- }
- }
-
- mEglDisplay = dpy;
- mEglContext = ctx;
- mTexName = tex;
- mAttached = true;
-
- return OK;
-}
-
-status_t SurfaceTexture::syncForReleaseLocked(EGLDisplay dpy) {
- ST_LOGV("syncForReleaseLocked");
-
- if (mUseFenceSync && mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
- EGLSyncKHR fence = mEGLSlots[mCurrentTexture].mFence;
- if (fence != EGL_NO_SYNC_KHR) {
- // There is already a fence for the current slot. We need to wait
- // on that before replacing it with another fence to ensure that all
- // outstanding buffer accesses have completed before the producer
- // accesses it.
- EGLint result = eglClientWaitSyncKHR(dpy, fence, 0, 1000000000);
- if (result == EGL_FALSE) {
- ST_LOGE("syncForReleaseLocked: error waiting for previous "
- "fence: %#x", eglGetError());
- return UNKNOWN_ERROR;
- } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
- ST_LOGE("syncForReleaseLocked: timeout waiting for previous "
- "fence");
- return TIMED_OUT;
- }
- eglDestroySyncKHR(dpy, fence);
- }
-
- // Create a fence for the outstanding accesses in the current OpenGL ES
- // context.
- fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
- if (fence == EGL_NO_SYNC_KHR) {
- ST_LOGE("syncForReleaseLocked: error creating fence: %#x",
- eglGetError());
- return UNKNOWN_ERROR;
- }
- glFlush();
- mEGLSlots[mCurrentTexture].mFence = fence;
- }
-
- return OK;
-}
-
-bool SurfaceTexture::isExternalFormat(uint32_t format)
-{
- switch (format) {
- // supported YUV formats
- case HAL_PIXEL_FORMAT_YV12:
- // Legacy/deprecated YUV formats
- case HAL_PIXEL_FORMAT_YCbCr_422_SP:
- case HAL_PIXEL_FORMAT_YCrCb_420_SP:
- case HAL_PIXEL_FORMAT_YCbCr_422_I:
- return true;
- }
-
- // Any OEM format needs to be considered
- if (format>=0x100 && format<=0x1FF)
- return true;
-
- return false;
-}
-
-GLenum SurfaceTexture::getCurrentTextureTarget() const {
- return mTexTarget;
-}
-
-void SurfaceTexture::getTransformMatrix(float mtx[16]) {
- Mutex::Autolock lock(mMutex);
- memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
-}
-
-void SurfaceTexture::setFilteringEnabled(bool enabled) {
- Mutex::Autolock lock(mMutex);
- bool needsRecompute = mFilteringEnabled != enabled;
- mFilteringEnabled = enabled;
- if (needsRecompute) {
- computeCurrentTransformMatrix();
- }
-}
-
-void SurfaceTexture::computeCurrentTransformMatrix() {
- ST_LOGV("computeCurrentTransformMatrix");
-
- float xform[16];
- for (int i = 0; i < 16; i++) {
- xform[i] = mtxIdentity[i];
- }
- if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
- float result[16];
- mtxMul(result, xform, mtxFlipH);
- for (int i = 0; i < 16; i++) {
- xform[i] = result[i];
- }
- }
- if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
- float result[16];
- mtxMul(result, xform, mtxFlipV);
- for (int i = 0; i < 16; i++) {
- xform[i] = result[i];
- }
- }
- if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
- float result[16];
- mtxMul(result, xform, mtxRot90);
- for (int i = 0; i < 16; i++) {
- xform[i] = result[i];
- }
- }
-
- sp<GraphicBuffer>& buf(mCurrentTextureBuf);
- Rect cropRect = mCurrentCrop;
- float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f;
- float bufferWidth = buf->getWidth();
- float bufferHeight = buf->getHeight();
- if (!cropRect.isEmpty()) {
- float shrinkAmount = 0.0f;
- if (mFilteringEnabled) {
- // In order to prevent bilinear sampling beyond the edge of the
- // crop rectangle we may need to shrink it by 2 texels in each
- // dimension. Normally this would just need to take 1/2 a texel
- // off each end, but because the chroma channels of YUV420 images
- // are subsampled we may need to shrink the crop region by a whole
- // texel on each side.
- switch (buf->getPixelFormat()) {
- case PIXEL_FORMAT_RGBA_8888:
- case PIXEL_FORMAT_RGBX_8888:
- case PIXEL_FORMAT_RGB_888:
- case PIXEL_FORMAT_RGB_565:
- case PIXEL_FORMAT_BGRA_8888:
- case PIXEL_FORMAT_RGBA_5551:
- case PIXEL_FORMAT_RGBA_4444:
- // We know there's no subsampling of any channels, so we
- // only need to shrink by a half a pixel.
- shrinkAmount = 0.5;
-
- default:
- // If we don't recognize the format, we must assume the
- // worst case (that we care about), which is YUV420.
- shrinkAmount = 1.0;
- }
- }
-
- // Only shrink the dimensions that are not the size of the buffer.
- if (cropRect.width() < bufferWidth) {
- tx = (float(cropRect.left) + shrinkAmount) / bufferWidth;
- sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) /
- bufferWidth;
- }
- if (cropRect.height() < bufferHeight) {
- ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) /
- bufferHeight;
- sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) /
- bufferHeight;
- }
- }
- float crop[16] = {
- sx, 0, 0, 0,
- 0, sy, 0, 0,
- 0, 0, 1, 0,
- tx, ty, 0, 1,
- };
-
- float mtxBeforeFlipV[16];
- mtxMul(mtxBeforeFlipV, crop, xform);
-
- // SurfaceFlinger expects the top of its window textures to be at a Y
- // coordinate of 0, so SurfaceTexture must behave the same way. We don't
- // want to expose this to applications, however, so we must add an
- // additional vertical flip to the transform after all the other transforms.
- mtxMul(mCurrentTransformMatrix, mtxFlipV, mtxBeforeFlipV);
-}
-
-nsecs_t SurfaceTexture::getTimestamp() {
- ST_LOGV("getTimestamp");
- Mutex::Autolock lock(mMutex);
- return mCurrentTimestamp;
-}
-
-void SurfaceTexture::setFrameAvailableListener(
- const sp<FrameAvailableListener>& listener) {
- ST_LOGV("setFrameAvailableListener");
- Mutex::Autolock lock(mMutex);
- mFrameAvailableListener = listener;
-}
-
-EGLImageKHR SurfaceTexture::createImage(EGLDisplay dpy,
- const sp<GraphicBuffer>& graphicBuffer) {
- EGLClientBuffer cbuf = (EGLClientBuffer)graphicBuffer->getNativeBuffer();
- EGLint attrs[] = {
- EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
- EGL_NONE,
- };
- EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
- EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
- if (image == EGL_NO_IMAGE_KHR) {
- EGLint error = eglGetError();
- ST_LOGE("error creating EGLImage: %#x", error);
- }
- return image;
-}
-
-sp<GraphicBuffer> SurfaceTexture::getCurrentBuffer() const {
- Mutex::Autolock lock(mMutex);
- return mCurrentTextureBuf;
-}
-
-Rect SurfaceTexture::getCurrentCrop() const {
- Mutex::Autolock lock(mMutex);
-
- Rect outCrop = mCurrentCrop;
- if (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
- int32_t newWidth = mCurrentCrop.width();
- int32_t newHeight = mCurrentCrop.height();
-
- if (newWidth * mDefaultHeight > newHeight * mDefaultWidth) {
- newWidth = newHeight * mDefaultWidth / mDefaultHeight;
- ST_LOGV("too wide: newWidth = %d", newWidth);
- } else if (newWidth * mDefaultHeight < newHeight * mDefaultWidth) {
- newHeight = newWidth * mDefaultHeight / mDefaultWidth;
- ST_LOGV("too tall: newHeight = %d", newHeight);
- }
-
- // The crop is too wide
- if (newWidth < mCurrentCrop.width()) {
- int32_t dw = (newWidth - mCurrentCrop.width())/2;
- outCrop.left -=dw;
- outCrop.right += dw;
- // The crop is too tall
- } else if (newHeight < mCurrentCrop.height()) {
- int32_t dh = (newHeight - mCurrentCrop.height())/2;
- outCrop.top -= dh;
- outCrop.bottom += dh;
- }
-
- ST_LOGV("getCurrentCrop final crop [%d,%d,%d,%d]",
- outCrop.left, outCrop.top,
- outCrop.right,outCrop.bottom);
- }
-
- return outCrop;
-}
-
-uint32_t SurfaceTexture::getCurrentTransform() const {
- Mutex::Autolock lock(mMutex);
- return mCurrentTransform;
-}
-
-uint32_t SurfaceTexture::getCurrentScalingMode() const {
- Mutex::Autolock lock(mMutex);
- return mCurrentScalingMode;
-}
-
-bool SurfaceTexture::isSynchronousMode() const {
- Mutex::Autolock lock(mMutex);
- return mBufferQueue->isSynchronousMode();
-}
-
-void SurfaceTexture::freeBufferLocked(int slotIndex) {
- ST_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
- mEGLSlots[slotIndex].mGraphicBuffer = 0;
- if (slotIndex == mCurrentTexture) {
- mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
- }
- EGLImageKHR img = mEGLSlots[slotIndex].mEglImage;
- if (img != EGL_NO_IMAGE_KHR) {
- ST_LOGV("destroying EGLImage dpy=%p img=%p", mEglDisplay, img);
- eglDestroyImageKHR(mEglDisplay, img);
- }
- mEGLSlots[slotIndex].mEglImage = EGL_NO_IMAGE_KHR;
-}
-
-void SurfaceTexture::abandon() {
- ST_LOGV("abandon");
- Mutex::Autolock lock(mMutex);
-
- if (!mAbandoned) {
- mAbandoned = true;
- mCurrentTextureBuf.clear();
-
- // destroy all egl buffers
- for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
- freeBufferLocked(i);
- }
-
- // disconnect from the BufferQueue
- mBufferQueue->consumerDisconnect();
- mBufferQueue.clear();
- }
-}
-
-void SurfaceTexture::setName(const String8& name) {
- Mutex::Autolock _l(mMutex);
- mName = name;
- mBufferQueue->setConsumerName(name);
-}
-
-status_t SurfaceTexture::setDefaultBufferFormat(uint32_t defaultFormat) {
- Mutex::Autolock lock(mMutex);
- return mBufferQueue->setDefaultBufferFormat(defaultFormat);
-}
-
-status_t SurfaceTexture::setConsumerUsageBits(uint32_t usage) {
- Mutex::Autolock lock(mMutex);
- usage |= DEFAULT_USAGE_FLAGS;
- return mBufferQueue->setConsumerUsageBits(usage);
-}
-
-status_t SurfaceTexture::setTransformHint(uint32_t hint) {
- Mutex::Autolock lock(mMutex);
- return mBufferQueue->setTransformHint(hint);
-}
-
-// Used for refactoring BufferQueue from SurfaceTexture
-// Should not be in final interface once users of SurfaceTexture are clean up.
-status_t SurfaceTexture::setSynchronousMode(bool enabled) {
- Mutex::Autolock lock(mMutex);
- return mBufferQueue->setSynchronousMode(enabled);
-}
-
-// Used for refactoring, should not be in final interface
-sp<BufferQueue> SurfaceTexture::getBufferQueue() const {
- Mutex::Autolock lock(mMutex);
- return mBufferQueue;
-}
-
-void SurfaceTexture::onFrameAvailable() {
- ST_LOGV("onFrameAvailable");
-
- sp<FrameAvailableListener> listener;
- { // scope for the lock
- Mutex::Autolock lock(mMutex);
- listener = mFrameAvailableListener;
- }
-
- if (listener != NULL) {
- ST_LOGV("actually calling onFrameAvailable");
- listener->onFrameAvailable();
- }
-}
-
-void SurfaceTexture::onBuffersReleased() {
- ST_LOGV("onBuffersReleased");
-
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- // Nothing to do if we're already abandoned.
- return;
- }
-
- uint32_t mask = 0;
- mBufferQueue->getReleasedBuffers(&mask);
- for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
- if (mask & (1 << i)) {
- freeBufferLocked(i);
- }
- }
-}
-
-void SurfaceTexture::dump(String8& result) const
-{
- char buffer[1024];
- dump(result, "", buffer, 1024);
-}
-
-void SurfaceTexture::dump(String8& result, const char* prefix,
- char* buffer, size_t SIZE) const
-{
- Mutex::Autolock _l(mMutex);
- snprintf(buffer, SIZE, "%smTexName=%d, mAbandoned=%d\n", prefix, mTexName,
- int(mAbandoned));
- result.append(buffer);
-
- snprintf(buffer, SIZE,
- "%snext : {crop=[%d,%d,%d,%d], transform=0x%02x, current=%d}\n",
- prefix, mCurrentCrop.left,
- mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
- mCurrentTransform, mCurrentTexture
- );
- result.append(buffer);
-
- if (!mAbandoned) {
- mBufferQueue->dump(result, prefix, buffer, SIZE);
- }
-}
-
-static void mtxMul(float out[16], const float a[16], const float b[16]) {
- out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3];
- out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3];
- out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3];
- out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3];
-
- out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7];
- out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7];
- out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7];
- out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7];
-
- out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11];
- out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11];
- out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11];
- out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11];
-
- out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15];
- out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15];
- out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15];
- out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15];
-}
-
-}; // namespace android
diff --git a/src/imports/nativemedia/SurfaceTexture_4_1.h b/src/imports/nativemedia/SurfaceTexture_4_1.h
deleted file mode 100644
index 33aac7f..0000000
--- a/src/imports/nativemedia/SurfaceTexture_4_1.h
+++ /dev/null
@@ -1,420 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_GUI_SURFACETEXTURE_H
-#define ANDROID_GUI_SURFACETEXTURE_H
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
-#include <gui/ISurfaceTexture.h>
-#include <BufferQueue.h>
-
-#include <ui/GraphicBuffer.h>
-
-#include <utils/String8.h>
-#include <utils/Vector.h>
-#include <utils/threads.h>
-
-#define ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID "mSurfaceTexture"
-
-namespace android {
-// ----------------------------------------------------------------------------
-
-
-class String8;
-
-class SurfaceTexture : public virtual RefBase,
- protected BufferQueue::ConsumerListener {
-public:
- struct FrameAvailableListener : public virtual RefBase {
- // onFrameAvailable() is called each time an additional frame becomes
- // available for consumption. This means that frames that are queued
- // while in asynchronous mode only trigger the callback if no previous
- // frames are pending. Frames queued while in synchronous mode always
- // trigger the callback.
- //
- // This is called without any lock held and can be called concurrently
- // by multiple threads.
- virtual void onFrameAvailable() = 0;
- };
-
- // SurfaceTexture constructs a new SurfaceTexture object. tex indicates the
- // name of the OpenGL ES texture to which images are to be streamed.
- // allowSynchronousMode specifies whether or not synchronous mode can be
- // enabled. texTarget specifies the OpenGL ES texture target to which the
- // texture will be bound in updateTexImage. useFenceSync specifies whether
- // fences should be used to synchronize access to buffers if that behavior
- // is enabled at compile-time. A custom bufferQueue can be specified
- // if behavior for queue/dequeue/connect etc needs to be customized.
- // Otherwise a default BufferQueue will be created and used.
- //
- // For legacy reasons, the SurfaceTexture is created in a state where it is
- // considered attached to an OpenGL ES context for the purposes of the
- // attachToContext and detachFromContext methods. However, despite being
- // considered "attached" to a context, the specific OpenGL ES context
- // doesn't get latched until the first call to updateTexImage. After that
- // point, all calls to updateTexImage must be made with the same OpenGL ES
- // context current.
- //
- // A SurfaceTexture may be detached from one OpenGL ES context and then
- // attached to a different context using the detachFromContext and
- // attachToContext methods, respectively. The intention of these methods is
- // purely to allow a SurfaceTexture to be transferred from one consumer
- // context to another. If such a transfer is not needed there is no
- // requirement that either of these methods be called.
- SurfaceTexture(GLuint tex, bool allowSynchronousMode = true,
- GLenum texTarget = GL_TEXTURE_EXTERNAL_OES, bool useFenceSync = true,
- const sp<BufferQueue> &bufferQueue = 0);
-
- virtual ~SurfaceTexture();
-
- // updateTexImage sets the image contents of the target texture to that of
- // the most recently queued buffer.
- //
- // This call may only be made while the OpenGL ES context to which the
- // target texture belongs is bound to the calling thread.
- status_t updateTexImage();
-
- // setBufferCountServer set the buffer count. If the client has requested
- // a buffer count using setBufferCount, the server-buffer count will
- // take effect once the client sets the count back to zero.
- status_t setBufferCountServer(int bufferCount);
-
- // getTransformMatrix retrieves the 4x4 texture coordinate transform matrix
- // associated with the texture image set by the most recent call to
- // updateTexImage.
- //
- // This transform matrix maps 2D homogeneous texture coordinates of the form
- // (s, t, 0, 1) with s and t in the inclusive range [0, 1] to the texture
- // coordinate that should be used to sample that location from the texture.
- // Sampling the texture outside of the range of this transform is undefined.
- //
- // This transform is necessary to compensate for transforms that the stream
- // content producer may implicitly apply to the content. By forcing users of
- // a SurfaceTexture to apply this transform we avoid performing an extra
- // copy of the data that would be needed to hide the transform from the
- // user.
- //
- // The matrix is stored in column-major order so that it may be passed
- // directly to OpenGL ES via the glLoadMatrixf or glUniformMatrix4fv
- // functions.
- void getTransformMatrix(float mtx[16]);
-
- // getTimestamp retrieves the timestamp associated with the texture image
- // set by the most recent call to updateTexImage.
- //
- // The timestamp is in nanoseconds, and is monotonically increasing. Its
- // other semantics (zero point, etc) are source-dependent and should be
- // documented by the source.
- int64_t getTimestamp();
-
- // setFrameAvailableListener sets the listener object that will be notified
- // when a new frame becomes available.
- void setFrameAvailableListener(const sp<FrameAvailableListener>& listener);
-
- // getAllocator retrieves the binder object that must be referenced as long
- // as the GraphicBuffers dequeued from this SurfaceTexture are referenced.
- // Holding this binder reference prevents SurfaceFlinger from freeing the
- // buffers before the client is done with them.
- sp<IBinder> getAllocator();
-
- // setDefaultBufferSize is used to set the size of buffers returned by
- // requestBuffers when a with and height of zero is requested.
- // A call to setDefaultBufferSize() may trigger requestBuffers() to
- // be called from the client.
- // The width and height parameters must be no greater than the minimum of
- // GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv).
- // An error due to invalid dimensions might not be reported until
- // updateTexImage() is called.
- status_t setDefaultBufferSize(uint32_t width, uint32_t height);
-
- // setFilteringEnabled sets whether the transform matrix should be computed
- // for use with bilinear filtering.
- void setFilteringEnabled(bool enabled);
-
- // getCurrentBuffer returns the buffer associated with the current image.
- sp<GraphicBuffer> getCurrentBuffer() const;
-
- // getCurrentTextureTarget returns the texture target of the current
- // texture as returned by updateTexImage().
- GLenum getCurrentTextureTarget() const;
-
- // getCurrentCrop returns the cropping rectangle of the current buffer.
- Rect getCurrentCrop() const;
-
- // getCurrentTransform returns the transform of the current buffer.
- uint32_t getCurrentTransform() const;
-
- // getCurrentScalingMode returns the scaling mode of the current buffer.
- uint32_t getCurrentScalingMode() const;
-
- // isSynchronousMode returns whether the SurfaceTexture is currently in
- // synchronous mode.
- bool isSynchronousMode() const;
-
- // abandon frees all the buffers and puts the SurfaceTexture into the
- // 'abandoned' state. Once put in this state the SurfaceTexture can never
- // leave it. When in the 'abandoned' state, all methods of the
- // ISurfaceTexture interface will fail with the NO_INIT error.
- //
- // Note that while calling this method causes all the buffers to be freed
- // from the perspective of the the SurfaceTexture, if there are additional
- // references on the buffers (e.g. if a buffer is referenced by a client or
- // by OpenGL ES as a texture) then those buffer will remain allocated.
- void abandon();
-
- // set the name of the SurfaceTexture that will be used to identify it in
- // log messages.
- void setName(const String8& name);
-
- // These functions call the corresponding BufferQueue implementation
- // so the refactoring can proceed smoothly
- status_t setDefaultBufferFormat(uint32_t defaultFormat);
- status_t setConsumerUsageBits(uint32_t usage);
- status_t setTransformHint(uint32_t hint);
- virtual status_t setSynchronousMode(bool enabled);
-
- // getBufferQueue returns the BufferQueue object to which this
- // SurfaceTexture is connected.
- sp<BufferQueue> getBufferQueue() const;
-
- // detachFromContext detaches the SurfaceTexture from the calling thread's
- // current OpenGL ES context. This context must be the same as the context
- // that was current for previous calls to updateTexImage.
- //
- // Detaching a SurfaceTexture from an OpenGL ES context will result in the
- // deletion of the OpenGL ES texture object into which the images were being
- // streamed. After a SurfaceTexture has been detached from the OpenGL ES
- // context calls to updateTexImage will fail returning INVALID_OPERATION
- // until the SurfaceTexture is attached to a new OpenGL ES context using the
- // attachToContext method.
- status_t detachFromContext();
-
- // attachToContext attaches a SurfaceTexture that is currently in the
- // 'detached' state to the current OpenGL ES context. A SurfaceTexture is
- // in the 'detached' state iff detachFromContext has successfully been
- // called and no calls to attachToContext have succeeded since the last
- // detachFromContext call. Calls to attachToContext made on a
- // SurfaceTexture that is not in the 'detached' state will result in an
- // INVALID_OPERATION error.
- //
- // The tex argument specifies the OpenGL ES texture object name in the
- // new context into which the image contents will be streamed. A successful
- // call to attachToContext will result in this texture object being bound to
- // the texture target and populated with the image contents that were
- // current at the time of the last call to detachFromContext.
- status_t attachToContext(GLuint tex);
-
- // dump our state in a String
- virtual void dump(String8& result) const;
- virtual void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const;
-
-protected:
-
- // Implementation of the BufferQueue::ConsumerListener interface. These
- // calls are used to notify the SurfaceTexture of asynchronous events in the
- // BufferQueue.
- virtual void onFrameAvailable();
- virtual void onBuffersReleased();
-
- static bool isExternalFormat(uint32_t format);
-
-private:
- // this version of updateTexImage() takes a functor used to reject or not
- // the newly acquired buffer.
- // this API is TEMPORARY and intended to be used by SurfaceFlinger only,
- // which is why class Layer is made a friend of SurfaceTexture below.
- class BufferRejecter {
- friend class SurfaceTexture;
- virtual bool reject(const sp<GraphicBuffer>& buf,
- const BufferQueue::BufferItem& item) = 0;
- protected:
- virtual ~BufferRejecter() { }
- };
- friend class Layer;
- status_t updateTexImage(BufferRejecter* rejecter);
-
- // createImage creates a new EGLImage from a GraphicBuffer.
- EGLImageKHR createImage(EGLDisplay dpy,
- const sp<GraphicBuffer>& graphicBuffer);
-
- // freeBufferLocked frees up the given buffer slot. If the slot has been
- // initialized this will release the reference to the GraphicBuffer in that
- // slot and destroy the EGLImage in that slot. Otherwise it has no effect.
- //
- // This method must be called with mMutex locked.
- void freeBufferLocked(int slotIndex);
-
- // computeCurrentTransformMatrix computes the transform matrix for the
- // current texture. It uses mCurrentTransform and the current GraphicBuffer
- // to compute this matrix and stores it in mCurrentTransformMatrix.
- void computeCurrentTransformMatrix();
-
- // syncForReleaseLocked performs the synchronization needed to release the
- // current slot from an OpenGL ES context. If needed it will set the
- // current slot's fence to guard against a producer accessing the buffer
- // before the outstanding accesses have completed.
- status_t syncForReleaseLocked(EGLDisplay dpy);
-
- // The default consumer usage flags that SurfaceTexture always sets on its
- // BufferQueue instance; these will be OR:d with any additional flags passed
- // from the SurfaceTexture user. In particular, SurfaceTexture will always
- // consume buffers as hardware textures.
- static const uint32_t DEFAULT_USAGE_FLAGS = GraphicBuffer::USAGE_HW_TEXTURE;
-
- // mCurrentTextureBuf is the graphic buffer of the current texture. It's
- // possible that this buffer is not associated with any buffer slot, so we
- // must track it separately in order to support the getCurrentBuffer method.
- sp<GraphicBuffer> mCurrentTextureBuf;
-
- // mCurrentCrop is the crop rectangle that applies to the current texture.
- // It gets set each time updateTexImage is called.
- Rect mCurrentCrop;
-
- // mCurrentTransform is the transform identifier for the current texture. It
- // gets set each time updateTexImage is called.
- uint32_t mCurrentTransform;
-
- // mCurrentScalingMode is the scaling mode for the current texture. It gets
- // set to each time updateTexImage is called.
- uint32_t mCurrentScalingMode;
-
- // mCurrentTransformMatrix is the transform matrix for the current texture.
- // It gets computed by computeTransformMatrix each time updateTexImage is
- // called.
- float mCurrentTransformMatrix[16];
-
- // mCurrentTimestamp is the timestamp for the current texture. It
- // gets set each time updateTexImage is called.
- int64_t mCurrentTimestamp;
-
- uint32_t mDefaultWidth, mDefaultHeight;
-
- // mFilteringEnabled indicates whether the transform matrix is computed for
- // use with bilinear filtering. It defaults to true and is changed by
- // setFilteringEnabled().
- bool mFilteringEnabled;
-
- // mTexName is the name of the OpenGL texture to which streamed images will
- // be bound when updateTexImage is called. It is set at construction time
- // and can be changed with a call to attachToContext.
- GLuint mTexName;
-
- // mUseFenceSync indicates whether creation of the EGL_KHR_fence_sync
- // extension should be used to prevent buffers from being dequeued before
- // it's safe for them to be written. It gets set at construction time and
- // never changes.
- const bool mUseFenceSync;
-
- // mTexTarget is the GL texture target with which the GL texture object is
- // associated. It is set in the constructor and never changed. It is
- // almost always GL_TEXTURE_EXTERNAL_OES except for one use case in Android
- // Browser. In that case it is set to GL_TEXTURE_2D to allow
- // glCopyTexSubImage to read from the texture. This is a hack to work
- // around a GL driver limitation on the number of FBO attachments, which the
- // browser's tile cache exceeds.
- const GLenum mTexTarget;
-
- // EGLSlot contains the information and object references that
- // SurfaceTexture maintains about a BufferQueue buffer slot.
- struct EGLSlot {
- EGLSlot()
- : mEglImage(EGL_NO_IMAGE_KHR),
- mFence(EGL_NO_SYNC_KHR) {
- }
-
- sp<GraphicBuffer> mGraphicBuffer;
-
- // mEglImage is the EGLImage created from mGraphicBuffer.
- EGLImageKHR mEglImage;
-
- // mFence is the EGL sync object that must signal before the buffer
- // associated with this buffer slot may be dequeued. It is initialized
- // to EGL_NO_SYNC_KHR when the buffer is created and (optionally, based
- // on a compile-time option) set to a new sync object in updateTexImage.
- EGLSyncKHR mFence;
- };
-
- // mEglDisplay is the EGLDisplay with which this SurfaceTexture is currently
- // associated. It is intialized to EGL_NO_DISPLAY and gets set to the
- // current display when updateTexImage is called for the first time and when
- // attachToContext is called.
- EGLDisplay mEglDisplay;
-
- // mEglContext is the OpenGL ES context with which this SurfaceTexture is
- // currently associated. It is initialized to EGL_NO_CONTEXT and gets set
- // to the current GL context when updateTexImage is called for the first
- // time and when attachToContext is called.
- EGLContext mEglContext;
-
- // mEGLSlots stores the buffers that have been allocated by the BufferQueue
- // for each buffer slot. It is initialized to null pointers, and gets
- // filled in with the result of BufferQueue::acquire when the
- // client dequeues a buffer from a
- // slot that has not yet been used. The buffer allocated to a slot will also
- // be replaced if the requested buffer usage or geometry differs from that
- // of the buffer allocated to a slot.
- EGLSlot mEGLSlots[BufferQueue::NUM_BUFFER_SLOTS];
-
- // mAbandoned indicates that the BufferQueue will no longer be used to
- // consume images buffers pushed to it using the ISurfaceTexture interface.
- // It is initialized to false, and set to true in the abandon method. A
- // BufferQueue that has been abandoned will return the NO_INIT error from
- // all ISurfaceTexture methods capable of returning an error.
- bool mAbandoned;
-
- // mName is a string used to identify the SurfaceTexture in log messages.
- // It can be set by the setName method.
- String8 mName;
-
- // mFrameAvailableListener is the listener object that will be called when a
- // new frame becomes available. If it is not NULL it will be called from
- // queueBuffer.
- sp<FrameAvailableListener> mFrameAvailableListener;
-
- // mCurrentTexture is the buffer slot index of the buffer that is currently
- // bound to the OpenGL texture. It is initialized to INVALID_BUFFER_SLOT,
- // indicating that no buffer slot is currently bound to the texture. Note,
- // however, that a value of INVALID_BUFFER_SLOT does not necessarily mean
- // that no buffer is bound to the texture. A call to setBufferCount will
- // reset mCurrentTexture to INVALID_BUFFER_SLOT.
- int mCurrentTexture;
-
- // The SurfaceTexture has-a BufferQueue and is responsible for creating this object
- // if none is supplied
- sp<BufferQueue> mBufferQueue;
-
- // mAttached indicates whether the SurfaceTexture is currently attached to
- // an OpenGL ES context. For legacy reasons, this is initialized to true,
- // indicating that the SurfaceTexture is considered to be attached to
- // whatever context is current at the time of the first updateTexImage call.
- // It is set to false by detachFromContext, and then set to true again by
- // attachToContext.
- bool mAttached;
-
- // mMutex is the mutex used to prevent concurrent access to the member
- // variables of SurfaceTexture objects. It must be locked whenever the
- // member variables are accessed.
- mutable Mutex mMutex;
-};
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_GUI_SURFACETEXTURE_H
diff --git a/src/imports/nativemedia/main.cpp b/src/imports/nativemedia/main.cpp
deleted file mode 100644
index b14b3d0..0000000
--- a/src/imports/nativemedia/main.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include <QtGui>
-
-void initializeOMX();
-void render(QOpenGLContext *context, QWindow *surface);
-
-class Renderer : public QObject
-{
- Q_OBJECT
-public:
- Renderer(QWindow *surface)
- : surface(surface)
- {
- context = new QOpenGLContext;
-
- context->create();
- context->makeCurrent(surface);
-
- initializeOMX();
- qDebug() << "OMX initialized";
- }
-
-public slots:
- void render() {
- ::render(context, surface);
- }
-
-public:
- QWindow *surface;
- QOpenGLContext *context;
-} *renderer;
-
-void triggerRender()
-{
- QTimer::singleShot(0, renderer, SLOT(render()));
-}
-
-int main(int argc, char *argv[])
-{
- QGuiApplication app(argc, argv);
-
- QScreen *screen = QGuiApplication::primaryScreen();
-
- qDebug() << "Screen geometry:" << screen->geometry();
-
- QWindow window;
- window.setSurfaceType(QWindow::OpenGLSurface);
- window.setGeometry(screen->geometry());
- window.show();
-
- renderer = new Renderer(&window);
-
- return app.exec();
-}
-
-#include "main.moc"
diff --git a/src/imports/nativemedia/nativemedia.pro b/src/imports/nativemedia/nativemedia.pro
deleted file mode 100644
index 027608d..0000000
--- a/src/imports/nativemedia/nativemedia.pro
+++ /dev/null
@@ -1,21 +0,0 @@
-######################################################################
-# Automatically generated by qmake (3.0) Thu Mar 7 13:00:32 2013
-######################################################################
-
-CXX_MODULE = qml
-TARGET = android_omx
-TARGETPATH = QtAndroidOmx
-IMPORT_VERSION = 1.0
-
-INCLUDEPATH += $$ANDROID_BUILD_TOP/development/ndk/platforms/android-14/include/
-
-LIBS += -lOpenMAXAL -lui -lgui -lutils -lcutils -lbinder
-
-QT += qml quick
-
-# Input
-HEADERS += omxnode.h omxplayer.h
-SOURCES += omx.cpp SurfaceTexture.cpp BufferQueue.cpp omxnode.cpp omxmodule.cpp
-
-load(qml_plugin)
-
diff --git a/src/imports/nativemedia/omx.cpp b/src/imports/nativemedia/omx.cpp
deleted file mode 100644
index b2ad4bc..0000000
--- a/src/imports/nativemedia/omx.cpp
+++ /dev/null
@@ -1,666 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include <OMXAL/OpenMAXAL.h>
-#include <OMXAL/OpenMAXAL_Android.h>
-
-#include <SurfaceTexture.h>
-#include <gui/SurfaceTextureClient.h>
-
-#include "omxplayer.h"
-
-#include <QtGui>
-
-#include <cassert>
-
-// number of required interfaces for the MediaPlayer creation
-#define NB_MAXAL_INTERFACES 3 // XAAndroidBufferQueueItf, XAStreamInformationItf and XAPlayItf
-
-// number of buffers in our buffer queue, an arbitrary number
-#define NB_BUFFERS 8
-
-// we're streaming MPEG-2 transport stream data, operate on transport stream block size
-#define MPEG2_TS_PACKET_SIZE 188
-
-// number of MPEG-2 transport stream blocks per buffer, an arbitrary number
-#define PACKETS_PER_BUFFER 10
-
-// determines how much memory we're dedicating to memory caching
-#define BUFFER_SIZE (PACKETS_PER_BUFFER*MPEG2_TS_PACKET_SIZE)
-
-using namespace android;
-
-// constant to identify a buffer context which is the end of the stream to decode
-static const int kEosBufferCntxt = 1980; // a magic value we can compare against
-
-OmxPlayer::~OmxPlayer()
-{
-}
-
-struct OmxContext : public OmxPlayer {
- // engine interfaces
- XAObjectItf engineObject;
- XAEngineItf engineEngine;
-
- // output mix interfaces
- XAObjectItf outputMixObject;
-
- // streaming media player interfaces
- XAObjectItf playerObj;
- XAPlayItf playerPlayItf;
- XAAndroidBufferQueueItf playerBQItf;
- XAStreamInformationItf playerStreamInfoItf;
- XAVolumeItf playerVolItf;
-
- // where we cache in memory the data to play
- // note this memory is re-used by the buffer queue callback
- char dataCache[BUFFER_SIZE * NB_BUFFERS];
-
- // handle of the file to play
- FILE *file;
-
- // has the app reached the end of the file
- bool reachedEof;
-
- // For mutual exclusion between callback thread and application thread(s).
- // The mutex protects reachedEof, discontinuity,
- // The condition is signalled when a discontinuity is acknowledged.
-
- pthread_mutex_t mutex;
- pthread_cond_t cond;
-
- sp<SurfaceTexture> surfaceTexture;
- sp<SurfaceTexture> surfaceTextureClient;
-
- int currentFrame;
- GLuint textureId;
-
- // for render, useful for debugging
- QOpenGLShaderProgram *program;
-
- int vertexLocation;
- int texCoordLocation;
- int textureLocation;
-
- OmxContext()
- : engineObject(0)
- , engineEngine(0)
- , outputMixObject(0)
- , playerObj(0)
- , playerPlayItf(0)
- , playerBQItf(0)
- , playerStreamInfoItf(0)
- , playerVolItf(0)
- , file(0)
- , reachedEof(false)
- , mutex(PTHREAD_MUTEX_INITIALIZER)
- , cond(PTHREAD_COND_INITIALIZER)
- , currentFrame(-1)
- , textureId(0)
- , program(0)
- , vertexLocation(0)
- , texCoordLocation(0)
- , textureLocation(0)
- {
- }
-
- ~OmxContext();
-
- void updateTexture()
- {
- if (surfaceTexture.get())
- surfaceTexture->updateTexImage();
- }
-
- bool hasFrame()
- {
- return currentFrame >= 0;
- }
-
- void setPaused(bool paused);
-
- bool initialize(const QByteArray &filename);
- bool enqueueInitialBuffers(bool discontinuity);
-
- XAresult AndroidBufferQueueCallback(
- XAAndroidBufferQueueItf caller,
- void *pCallbackContext,
- void *pBufferContext,
- void *pBufferData,
- XAuint32 dataSize,
- XAuint32 dataUsed,
- const XAAndroidBufferItem *pItems,
- XAuint32 itemsLength);
-
- void StreamChangeCallback(XAStreamInformationItf caller,
- XAuint32 eventId,
- XAuint32 streamIndex,
- void * pEventData,
- void * pContext );
-
- void render(QOpenGLContext *context, QWindow *surface);
-};
-
-static XAresult AndroidBufferQueueCallback(
- XAAndroidBufferQueueItf caller,
- void *pCallbackContext, /* input */
- void *pBufferContext, /* input */
- void *pBufferData, /* input */
- XAuint32 dataSize, /* input */
- XAuint32 dataUsed, /* input */
- const XAAndroidBufferItem *pItems,/* input */
- XAuint32 itemsLength /* input */)
-{
- return static_cast<OmxContext *>(pCallbackContext)->AndroidBufferQueueCallback(
- caller, pCallbackContext, pBufferContext, pBufferData, dataSize, dataUsed, pItems, itemsLength);
-}
-
-// AndroidBufferQueueItf callback to supply MPEG-2 TS packets to the media player
-XAresult OmxContext::AndroidBufferQueueCallback(
- XAAndroidBufferQueueItf caller,
- void *pCallbackContext, /* input */
- void *pBufferContext, /* input */
- void *pBufferData, /* input */
- XAuint32 dataSize, /* input */
- XAuint32 dataUsed, /* input */
- const XAAndroidBufferItem *pItems,/* input */
- XAuint32 itemsLength /* input */)
-{
- XAresult res;
- int ok;
-
- // note there is never any contention on this mutex unless a discontinuity request is active
- ok = pthread_mutex_lock(&mutex);
- assert(0 == ok);
-
-#if 0
- // was a discontinuity requested?
- if (discontinuity) {
- // Note: can't rewind after EOS, which we send when reaching EOF
- // (don't send EOS if you plan to play more content through the same player)
- if (!reachedEof) {
- // clear the buffer queue
- res = (*playerBQItf)->Clear(playerBQItf);
- assert(XA_RESULT_SUCCESS == res);
- // rewind the data source so we are guaranteed to be at an appropriate point
- rewind(file);
- // Enqueue the initial buffers, with a discontinuity indicator on first buffer
- (void) enqueueInitialBuffers(JNI_TRUE);
- }
- // acknowledge the discontinuity request
- discontinuity = JNI_FALSE;
- ok = pthread_cond_signal(&cond);
- assert(0 == ok);
- goto exit;
- }
-#endif
-
- if ((pBufferData == NULL) && (pBufferContext != NULL)) {
- const int processedCommand = *(int *)pBufferContext;
- if (kEosBufferCntxt == processedCommand) {
- qDebug("EOS was processed\n");
- // our buffer with the EOS message has been consumed
- assert(0 == dataSize);
- goto exit;
- }
- }
-
- // pBufferData is a pointer to a buffer that we previously Enqueued
- assert((dataSize > 0) && ((dataSize % MPEG2_TS_PACKET_SIZE) == 0));
- assert(dataCache <= (char *) pBufferData && (char *) pBufferData <
- &dataCache[BUFFER_SIZE * NB_BUFFERS]);
- assert(0 == (((char *) pBufferData - dataCache) % BUFFER_SIZE));
-
- // don't bother trying to read more data once we've hit EOF
- if (reachedEof) {
- goto exit;
- }
-
- size_t nbRead;
- // note we do call fread from multiple threads, but never concurrently
- size_t bytesRead;
- bytesRead = fread(pBufferData, 1, BUFFER_SIZE, file);
- if (bytesRead > 0) {
- if ((bytesRead % MPEG2_TS_PACKET_SIZE) != 0) {
- qDebug("Dropping last packet because it is not whole");
- }
- size_t packetsRead = bytesRead / MPEG2_TS_PACKET_SIZE;
- size_t bufferSize = packetsRead * MPEG2_TS_PACKET_SIZE;
- res = (*caller)->Enqueue(caller, NULL /*pBufferContext*/,
- pBufferData /*pData*/,
- bufferSize /*dataLength*/,
- NULL /*pMsg*/,
- 0 /*msgLength*/);
- assert(XA_RESULT_SUCCESS == res);
- } else {
- // EOF or I/O error, signal EOS
- XAAndroidBufferItem msgEos[1];
- msgEos[0].itemKey = XA_ANDROID_ITEMKEY_EOS;
- msgEos[0].itemSize = 0;
- // EOS message has no parameters, so the total size of the message is the size of the key
- // plus the size if itemSize, both XAuint32
- res = (*caller)->Enqueue(caller, (void *)&kEosBufferCntxt /*pBufferContext*/,
- NULL /*pData*/, 0 /*dataLength*/,
- msgEos /*pMsg*/,
- sizeof(XAuint32)*2 /*msgLength*/);
- assert(XA_RESULT_SUCCESS == res);
- reachedEof = true;
- }
-
-exit:
- ok = pthread_mutex_unlock(&mutex);
- assert(0 == ok);
- return XA_RESULT_SUCCESS;
-}
-
-// callback invoked whenever there is new or changed stream information
-static void StreamChangeCallback(XAStreamInformationItf caller,
- XAuint32 eventId,
- XAuint32 streamIndex,
- void * pEventData,
- void * pContext )
-{
- static_cast<OmxContext *>(pContext)->StreamChangeCallback(
- caller, eventId, streamIndex, pEventData, pContext);
-}
-
-// callback invoked whenever there is new or changed stream information
-void OmxContext::StreamChangeCallback(XAStreamInformationItf caller,
- XAuint32 eventId,
- XAuint32 streamIndex,
- void * pEventData,
- void * pContext )
-{
- qDebug("StreamChangeCallback called for stream %u", streamIndex);
-
- switch (eventId) {
- case XA_STREAMCBEVENT_PROPERTYCHANGE: {
- /** From spec 1.0.1:
- "This event indicates that stream property change has occurred.
- The streamIndex parameter identifies the stream with the property change.
- The pEventData parameter for this event is not used and shall be ignored."
- */
-
- XAresult res;
- XAuint32 domain;
- res = (*caller)->QueryStreamType(caller, streamIndex, &domain);
- assert(XA_RESULT_SUCCESS == res);
- switch (domain) {
- case XA_DOMAINTYPE_VIDEO: {
- XAVideoStreamInformation videoInfo;
- res = (*caller)->QueryStreamInformation(caller, streamIndex, &videoInfo);
- assert(XA_RESULT_SUCCESS == res);
- qDebug("Found video size %u x %u, codec ID=%u, frameRate=%u, bitRate=%u, duration=%u ms",
- videoInfo.width, videoInfo.height, videoInfo.codecId, videoInfo.frameRate,
- videoInfo.bitRate, videoInfo.duration);
- emit videoSize(videoInfo.width, videoInfo.height);
- } break;
- default:
- fprintf(stderr, "Unexpected domain %u\n", domain);
- break;
- }
- } break;
- default:
- fprintf(stderr, "Unexpected stream event ID %u\n", eventId);
- break;
- }
-}
-
-// Enqueue the initial buffers, and optionally signal a discontinuity in the first buffer
-bool OmxContext::enqueueInitialBuffers(bool discontinuity)
-{
-
- /* Fill our cache.
- * We want to read whole packets (integral multiples of MPEG2_TS_PACKET_SIZE).
- * fread returns units of "elements" not bytes, so we ask for 1-byte elements
- * and then check that the number of elements is a multiple of the packet size.
- */
- size_t bytesRead;
- bytesRead = fread(dataCache, 1, BUFFER_SIZE * NB_BUFFERS, file);
- if (bytesRead <= 0) {
- // could be premature EOF or I/O error
- return false;
- }
- if ((bytesRead % MPEG2_TS_PACKET_SIZE) != 0) {
- qDebug("Dropping last packet because it is not whole");
- }
- size_t packetsRead = bytesRead / MPEG2_TS_PACKET_SIZE;
- qDebug("Initially queueing %u packets", packetsRead);
-
- /* Enqueue the content of our cache before starting to play,
- we don't want to starve the player */
- size_t i;
- for (i = 0; i < NB_BUFFERS && packetsRead > 0; i++) {
- // compute size of this buffer
- size_t packetsThisBuffer = packetsRead;
- if (packetsThisBuffer > PACKETS_PER_BUFFER) {
- packetsThisBuffer = PACKETS_PER_BUFFER;
- }
- size_t bufferSize = packetsThisBuffer * MPEG2_TS_PACKET_SIZE;
- XAresult res;
- if (discontinuity) {
- // signal discontinuity
- XAAndroidBufferItem items[1];
- items[0].itemKey = XA_ANDROID_ITEMKEY_DISCONTINUITY;
- items[0].itemSize = 0;
- // DISCONTINUITY message has no parameters,
- // so the total size of the message is the size of the key
- // plus the size if itemSize, both XAuint32
- res = (*playerBQItf)->Enqueue(playerBQItf, NULL /*pBufferContext*/,
- dataCache + i*BUFFER_SIZE, bufferSize, items /*pMsg*/,
- sizeof(XAuint32)*2 /*msgLength*/);
- //discontinuity = false;
- } else {
- res = (*playerBQItf)->Enqueue(playerBQItf, NULL /*pBufferContext*/,
- dataCache + i*BUFFER_SIZE, bufferSize, NULL, 0);
- }
- assert(XA_RESULT_SUCCESS == res);
- packetsRead -= packetsThisBuffer;
- }
-
- return true;
-}
-
-class FrameCallback : public SurfaceTexture::FrameAvailableListener
-{
-public:
- FrameCallback(OmxContext *ctx)
- : context(ctx)
- {
- }
-
- void onFrameAvailable()
- {
- emit context->frameAvailable();
- ++context->currentFrame;
- }
-
-private:
- OmxContext *context;
-};
-
-OmxPlayer *OmxPlayer::create()
-{
- return new OmxContext;
-}
-
-bool OmxContext::initialize(const QByteArray &filename)
-{
- file = fopen(filename.data(), "rb");
- if (!file) {
- qWarning("Failed to open %s", filename.data());
- return false;
- }
-
- XAresult res;
-
- qDebug() << "Creating engine object";
-
- // create engine
- res = xaCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
- assert(XA_RESULT_SUCCESS == res);
-
- qDebug() << "Creating engine object succeeded?" << (res == XA_RESULT_SUCCESS);
-
- // realize the engine
- res = (*engineObject)->Realize(engineObject, XA_BOOLEAN_FALSE);
- assert(XA_RESULT_SUCCESS == res);
-
- qDebug() << "Realizing engine object succeeded?" << (res == XA_RESULT_SUCCESS);
-
- // get the engine interface, which is needed in order to create other objects
- res = (*engineObject)->GetInterface(engineObject, XA_IID_ENGINE, &engineEngine);
- assert(XA_RESULT_SUCCESS == res);
-
- qDebug() << "Getting engine interface succeeded?" << (res == XA_RESULT_SUCCESS);
-
- // create output mix
- res = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, NULL, NULL);
- assert(XA_RESULT_SUCCESS == res);
-
- qDebug() << "Creating output mix succeeded?" << (res == XA_RESULT_SUCCESS);
-
- // realize the output mix
- res = (*outputMixObject)->Realize(outputMixObject, XA_BOOLEAN_FALSE);
- assert(XA_RESULT_SUCCESS == res);
-
- qDebug() << "Realizing output mix succeeded?" << (res == XA_RESULT_SUCCESS);
-
- // configure data source
- XADataLocator_AndroidBufferQueue loc_abq = { XA_DATALOCATOR_ANDROIDBUFFERQUEUE, NB_BUFFERS };
- XADataFormat_MIME format_mime = {
- XA_DATAFORMAT_MIME, XA_ANDROID_MIME_MP2TS, XA_CONTAINERTYPE_MPEG_TS };
- XADataSource dataSrc = {&loc_abq, &format_mime};
-
- // configure audio sink
- XADataLocator_OutputMix loc_outmix = { XA_DATALOCATOR_OUTPUTMIX, outputMixObject };
- XADataSink audioSnk = { &loc_outmix, 0 };
-
- qDebug() << "Creating SurfaceTexture";
-
- glGenTextures(1, &textureId);
- surfaceTexture = new android::SurfaceTexture(textureId);
-
- qDebug() << "Creating SurfaceTextureClient";
-
- android::sp<android::SurfaceTextureClient> surfaceTextureClient = new android::SurfaceTextureClient(surfaceTexture);
-
- sp<SurfaceTexture::FrameAvailableListener> listener = new FrameCallback(this);
-
- surfaceTexture->setFrameAvailableListener(listener);
-
- // configure image video sink
- XADataLocator_NativeDisplay loc_nd = {
- XA_DATALOCATOR_NATIVEDISPLAY, // locatorType
- // the video sink must be an ANativeWindow created from a Surface or SurfaceTexture
- static_cast<ANativeWindow *>(surfaceTextureClient.get()), // hWindow
- // must be 0
- 0 // hDisplay
- };
- XADataSink imageVideoSink = {&loc_nd, 0};
-
- // declare interfaces to use
- XAboolean required[NB_MAXAL_INTERFACES]
- = {XA_BOOLEAN_TRUE, XA_BOOLEAN_TRUE, XA_BOOLEAN_TRUE};
- XAInterfaceID iidArray[NB_MAXAL_INTERFACES]
- = {XA_IID_PLAY, XA_IID_ANDROIDBUFFERQUEUESOURCE,
- XA_IID_STREAMINFORMATION};
-
-
- qDebug() << "Creating media player for engine" << engineEngine;
-
- // create media player
- res = (*engineEngine)->CreateMediaPlayer(engineEngine, &playerObj, &dataSrc,
- 0, &audioSnk, &imageVideoSink, 0, 0,
- NB_MAXAL_INTERFACES /*XAuint32 numInterfaces*/,
- iidArray /*const XAInterfaceID *pInterfaceIds*/,
- required /*const XAboolean *pInterfaceRequired*/);
-
- qDebug() << "CreateMediaPlayer succeeded?" << (res == XA_RESULT_SUCCESS);
-
- // realize the player
- res = (*playerObj)->Realize(playerObj, XA_BOOLEAN_FALSE);
-
- qDebug() << "Realize media player succeeded?" << (res == XA_RESULT_SUCCESS);
-
- // get the play interface
- res = (*playerObj)->GetInterface(playerObj, XA_IID_PLAY, &playerPlayItf);
-
- qDebug() << "Get play interface succeeded?" << (res == XA_RESULT_SUCCESS);
-
- // get the stream information interface (for video size)
- res = (*playerObj)->GetInterface(playerObj, XA_IID_STREAMINFORMATION, &playerStreamInfoItf);
-
- qDebug() << "Get stream information interface succeeded?" << (res == XA_RESULT_SUCCESS);
-
- // get the volume interface
- res = (*playerObj)->GetInterface(playerObj, XA_IID_VOLUME, &playerVolItf);
-
- qDebug() << "Get volume interface succeeded?" << (res == XA_RESULT_SUCCESS);
-
- // get the Android buffer queue interface
- res = (*playerObj)->GetInterface(playerObj, XA_IID_ANDROIDBUFFERQUEUESOURCE, &playerBQItf);
-
- qDebug() << "Get buffer queue interface succeeded?" << (res == XA_RESULT_SUCCESS);
-
- // specify which events we want to be notified of
- res = (*playerBQItf)->SetCallbackEventsMask(playerBQItf, XA_ANDROIDBUFFERQUEUEEVENT_PROCESSED);
-
- qDebug() << "Setting callback events mask succeeded?" << (res == XA_RESULT_SUCCESS);
-
- // register the callback from which OpenMAX AL can retrieve the data to play
- res = (*playerBQItf)->RegisterCallback(playerBQItf, ::AndroidBufferQueueCallback, this);
-
- qDebug() << "Registering buffer queue callback succeeded?" << (res == XA_RESULT_SUCCESS);
-
- // we want to be notified of the video size once it's found, so we register a callback for that
- res = (*playerStreamInfoItf)->RegisterStreamChangeCallback(playerStreamInfoItf,
- ::StreamChangeCallback, this);
-
- qDebug() << "Registering stream change callback succeeded?" << (res == XA_RESULT_SUCCESS);
-
- // enqueue the initial buffers
- if (!enqueueInitialBuffers(false))
- return false;
-
- qDebug() << "Enqueued initial buffers";
-
- // prepare the player
- res = (*playerPlayItf)->SetPlayState(playerPlayItf, XA_PLAYSTATE_PAUSED);
-
- qDebug() << "Preparing player (setting play state paused) succeeded?" << (res == XA_RESULT_SUCCESS);
-
- // set the volume
- res = (*playerVolItf)->SetVolumeLevel(playerVolItf, 0);
-
- qDebug() << "Setting volume level succeeded?" << (res == XA_RESULT_SUCCESS);
-
- return true;
-}
-
-OmxContext::~OmxContext()
-{
- if (!file)
- return;
-
- // destroy streaming media player object, and invalidate all associated interfaces
- if (playerObj != NULL) {
- (*playerObj)->Destroy(playerObj);
- playerObj = NULL;
- playerPlayItf = NULL;
- playerBQItf = NULL;
- playerStreamInfoItf = NULL;
- playerVolItf = NULL;
- }
-
- // destroy output mix object, and invalidate all associated interfaces
- if (outputMixObject != NULL) {
- (*outputMixObject)->Destroy(outputMixObject);
- outputMixObject = NULL;
- }
-
- // destroy engine object, and invalidate all associated interfaces
- if (engineObject != NULL) {
- (*engineObject)->Destroy(engineObject);
- engineObject = NULL;
- engineEngine = NULL;
- }
-}
-
-void OmxContext::setPaused(bool paused)
-{
- XAresult res;
-
- // make sure the streaming media player was created
- if (NULL != playerPlayItf) {
- // set the player's state
- res = (*playerPlayItf)->SetPlayState(playerPlayItf, paused ?
- XA_PLAYSTATE_PAUSED : XA_PLAYSTATE_PLAYING);
- }
-}
-
-void OmxContext::render(QOpenGLContext *context, QWindow *surface)
-{
- context->makeCurrent(surface);
-
- glClearColor(0, 0, 0, 1);
- glClear(GL_COLOR_BUFFER_BIT);
-
- if (currentFrame >= 0) {
- surfaceTexture->updateTexImage();
-
- if (!program) {
- qDebug() << "Received first video frame, starting to render";
-
- program = new QOpenGLShaderProgram;
-
- program->addShaderFromSourceCode(QOpenGLShader::Vertex,
- "attribute highp vec4 vertex;\n"
- "attribute highp vec2 texCoord;\n"
- "varying highp vec2 coord;\n"
- "void main(void)\n"
- "{\n"
- " coord = texCoord;\n"
- " gl_Position = vertex;\n"
- "}");
- program->addShaderFromSourceCode(QOpenGLShader::Fragment,
- "#extension GL_OES_EGL_image_external : require\n"
- "uniform samplerExternalOES tex;\n"
- "varying highp vec2 coord;\n"
- "void main(void)\n"
- "{\n"
- " gl_FragColor = texture2D(tex, coord);\n"
- "}");
-
- program->link();
-
- vertexLocation = program->attributeLocation("vertex");
- texCoordLocation = program->attributeLocation("texCoord");
- textureLocation = program->uniformLocation("tex");
-
- qDebug() << "attribute locations" << vertexLocation << texCoordLocation;
- qDebug() << "uniform location" << textureLocation;
- }
-
- program->bind();
-
- static GLfloat const triangleVertices[] = {
- -1, -3,
- 3, 1,
- -1, 1
- };
-
- static GLfloat const triangleTexCoords[] = {
- 0, 2,
- 2, 0,
- 0, 0
- };
-
- program->enableAttributeArray(vertexLocation);
- program->setAttributeArray(vertexLocation, triangleVertices, 2);
- program->enableAttributeArray(texCoordLocation);
- program->setAttributeArray(texCoordLocation, triangleTexCoords, 2);
-
- glDrawArrays(GL_TRIANGLES, 0, 3);
-
- program->disableAttributeArray(vertexLocation);
- program->disableAttributeArray(texCoordLocation);
- }
-
- context->swapBuffers(surface);
-}
diff --git a/src/imports/nativemedia/omxmodule.cpp b/src/imports/nativemedia/omxmodule.cpp
deleted file mode 100644
index 2daa154..0000000
--- a/src/imports/nativemedia/omxmodule.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include "omxnode.h"
-#include <QtQml/QQmlExtensionPlugin>
-
-class QAndroidOmxModule : public QQmlExtensionPlugin
-{
- Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
-
-public:
- virtual void registerTypes(const char *uri)
- {
- Q_ASSERT(QLatin1String(uri) == QLatin1String("QtAndroidOmx"));
-
- qmlRegisterType<OmxItem>(uri, 1, 0, "OmxItem");
- }
-};
-
-#include "omxmodule.moc"
-
diff --git a/src/imports/nativemedia/omxnode.cpp b/src/imports/nativemedia/omxnode.cpp
deleted file mode 100644
index 27ec1da..0000000
--- a/src/imports/nativemedia/omxnode.cpp
+++ /dev/null
@@ -1,204 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include "omxnode.h"
-
-#include <QtGui/QOpenGLContext>
-#include <QtQuick/qsgtexture.h>
-#include <QtQuick/qquickwindow.h>
-
-#include <QTimer>
-
-static const char omx_texture_material_vertex[] =
- "uniform highp mat4 qt_Matrix; \n"
- "attribute highp vec4 qt_VertexPosition; \n"
- "attribute highp vec2 qt_VertexTexCoord; \n"
- "varying highp vec2 qt_TexCoord; \n"
- "void main() { \n"
- " qt_TexCoord = qt_VertexTexCoord; \n"
- " gl_Position = qt_Matrix * qt_VertexPosition; \n"
- "}";
-
-
-static const char omx_texture_material_fragment[] =
- "#extension GL_OES_EGL_image_external : require \n"
- "varying highp vec2 qt_TexCoord; \n"
- "uniform samplerExternalOES qt_Texture; \n"
- "uniform lowp float qt_Opacity; \n"
- "void main() { \n"
- " gl_FragColor = texture2D(qt_Texture, qt_TexCoord) * qt_Opacity; \n"
- "}";
-
-QList<QByteArray> OmxTextureMaterial::attributes() const
-{
- QList<QByteArray> attributeList;
- attributeList << "qt_VertexPosition";
- attributeList << "qt_VertexTexCoord";
- return attributeList;
-}
-
-void OmxTextureMaterial::updateState(const OmxTextureState *newState, const OmxTextureState *oldState)
-{
- Q_UNUSED(oldState);
- newState->player->updateTexture();
-}
-
-const char *OmxTextureMaterial::vertexShader() const
-{
- return omx_texture_material_vertex;
-}
-
-const char *OmxTextureMaterial::fragmentShader() const
-{
- return omx_texture_material_fragment;
-}
-
-OmxNode::OmxNode(OmxPlayer *player)
- : m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)
- , m_player(player)
- , m_initialized(false)
-{
- m_textureMaterial = OmxTextureMaterial::createMaterial();
- m_textureMaterial->state()->player = player;
-
- setGeometry(&m_geometry);
- setMaterial(m_textureMaterial);
-
- setFlag(UsePreprocess, true);
-}
-
-OmxNode::~OmxNode()
-{
- delete m_textureMaterial;
-}
-
-void OmxNode::preprocess()
-{
-}
-
-void OmxNode::setRect(const QRectF &rect)
-{
- if (m_rect == rect)
- return;
-
- printf("OmxNode::setRect(%f %f %f %f)\n", rect.x(), rect.y(), rect.width(), rect.height());
- m_rect = rect;
-
- QRectF sourceRect(0, 0, 1, 1);
- QSGGeometry::updateTexturedRectGeometry(&m_geometry, m_rect, sourceRect);
-}
-
-OmxItem::OmxItem()
- : m_player(OmxPlayer::create())
- , m_hasFrame(false)
- , m_initialized(false)
- , m_paused(false)
- , m_sourceWidth(0)
- , m_sourceHeight(0)
-{
- connect(m_player, SIGNAL(frameAvailable()), this, SLOT(triggerRender()));
- connect(m_player, SIGNAL(videoSize(int, int)), this, SLOT(videoSize(int, int)));
-
- setFlag(ItemHasContents, true);
-}
-
-void OmxItem::itemChange(ItemChange change, const ItemChangeData &)
-{
- if (change == ItemSceneChange) {
- QQuickWindow *win = window();
- if (!win)
- return;
-
- // Connect the beforeRendering signal to our paint function.
- // Since this call is executed on the rendering thread it must be
- // a Qt::DirectConnection
- connect(win, SIGNAL(beforeRendering()), this, SLOT(beforeRendering()), Qt::DirectConnection);
- }
-}
-
-
-OmxItem::~OmxItem()
-{
- delete m_player;
-}
-
-void OmxItem::triggerRender()
-{
- m_hasFrame = true;
- update();
-}
-
-void OmxItem::videoSize(int w, int h)
-{
- m_sourceWidth = w;
- m_sourceHeight = h;
-
- emit sourceWidthChanged();
- emit sourceHeightChanged();
-}
-
-void OmxItem::setSource(const QString &source)
-{
- if (m_initialized || source == m_source)
- return;
-
- m_source = source;
- emit sourceChanged();
- update();
-}
-
-void OmxItem::beforeRendering()
-{
- if (m_initialized || m_source.isNull())
- return;
-
- m_initialized = m_player->initialize(m_source.toLocal8Bit());
-
- GLuint tid;
- glGenTextures(1, &tid);
-
- // start playing if not paused
- if (m_initialized && !paused())
- m_player->setPaused(false);
-}
-
-QSGNode *OmxItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
-{
- if (!m_hasFrame)
- return 0;
-
- OmxNode *node;
- if (oldNode)
- node = static_cast<OmxNode *>(oldNode);
- else
- node = new OmxNode(m_player);
-
- node->setRect(boundingRect());
- node->markDirty(QSGNode::DirtyMaterial);
-
- return node;
-}
-
-void OmxItem::setPaused(bool p)
-{
- if (p == m_paused)
- return;
- m_player->setPaused(p);
- m_paused = p;
- emit pausedChanged();
-}
diff --git a/src/imports/nativemedia/omxnode.h b/src/imports/nativemedia/omxnode.h
deleted file mode 100644
index e658378..0000000
--- a/src/imports/nativemedia/omxnode.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#ifndef OMXNODE_H
-#define OMXNODE_H
-
-#include <QtQuick/qquickitem.h>
-
-#include <QtQuick/qsgnode.h>
-#include <QtQuick/qsgsimplematerial.h>
-
-#include "SurfaceTexture.h"
-
-#include "omxplayer.h"
-
-class QSGTexture;
-
-struct OmxTextureState {
- OmxPlayer *player;
-};
-
-class OmxNode : public QSGGeometryNode
-{
-public:
- OmxNode(OmxPlayer *player);
- ~OmxNode();
-
- void preprocess();
-
- void setRect(const QRectF &rect);
- inline void setRect(qreal x, qreal y, qreal w, qreal h) { setRect(QRectF(x, y, w, h)); }
-
- bool isTextureUpdated() const { return m_textureUpdated; }
- void setTextureUpdated(bool textureUpdated) { m_textureUpdated = textureUpdated; }
-
-private:
- bool m_textureUpdated;
-
- QSGGeometry m_geometry;
- QSGSimpleMaterial<OmxTextureState> *m_textureMaterial;
-
- QRectF m_rect;
- OmxPlayer *m_player;
- bool m_initialized;
-};
-
-class OmxTextureMaterial : public QSGSimpleMaterialShader<OmxTextureState>
-{
- QSG_DECLARE_SIMPLE_SHADER(OmxTextureMaterial, OmxTextureState)
-public:
- QList<QByteArray> attributes() const;
-
- void updateState(const OmxTextureState *newState, const OmxTextureState *oldState);
-
-protected:
- const char *vertexShader() const;
- const char *fragmentShader() const;
-};
-
-class OmxItem : public QQuickItem
-{
- Q_OBJECT
- Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged FINAL)
- Q_PROPERTY(int sourceWidth READ sourceWidth NOTIFY sourceWidthChanged FINAL)
- Q_PROPERTY(int sourceHeight READ sourceHeight NOTIFY sourceHeightChanged FINAL)
- Q_PROPERTY(bool paused READ paused WRITE setPaused NOTIFY pausedChanged FINAL)
-public:
- OmxItem();
- virtual ~OmxItem();
-
- QString source() {
- return m_source;
- }
-
- int sourceWidth() {
- return m_sourceWidth;
- }
-
- int sourceHeight() {
- return m_sourceHeight;
- }
-
- bool paused() { return m_paused; }
- void setPaused(bool p);
-
- void setSource(const QString &source);
-
-signals:
- void sourceChanged();
- void sourceWidthChanged();
- void sourceHeightChanged();
- void pausedChanged();
-
-protected:
- QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
- void itemChange(ItemChange change, const ItemChangeData &);
-
-private slots:
- void triggerRender();
- void videoSize(int w, int h);
- void beforeRendering();
-
-private:
- OmxPlayer *m_player;
- bool m_hasFrame;
- bool m_initialized;
- bool m_paused;
- QString m_source;
- int m_sourceWidth;
- int m_sourceHeight;
-};
-
-#endif // OMXNODE_H
-
diff --git a/src/imports/nativemedia/omxplayer.h b/src/imports/nativemedia/omxplayer.h
deleted file mode 100644
index 05bb224..0000000
--- a/src/imports/nativemedia/omxplayer.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#ifndef OMXPLAYER_H
-#define OMXPLAYER_H
-
-#include <QObject>
-
-class OmxPlayer : public QObject
-{
- Q_OBJECT
-public:
- virtual ~OmxPlayer() = 0;
-
- virtual void updateTexture() = 0;
- virtual bool initialize(const QByteArray &filename) = 0;
- virtual bool hasFrame() = 0;
- virtual void setPaused(bool paused) = 0;
-
- static OmxPlayer *create();
-
-signals:
- void frameAvailable();
- void videoSize(int w, int h);
-};
-
-#endif
diff --git a/src/imports/nativemedia/qmldir b/src/imports/nativemedia/qmldir
deleted file mode 100644
index 6c14ce6..0000000
--- a/src/imports/nativemedia/qmldir
+++ /dev/null
@@ -1,2 +0,0 @@
-module QtAndroidOmx
-plugin android_omx
diff --git a/src/imports/nativemedia/test.qml b/src/imports/nativemedia/test.qml
deleted file mode 100644
index 01a1bfd..0000000
--- a/src/imports/nativemedia/test.qml
+++ /dev/null
@@ -1,53 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-import QtQuick 2.0
-import QtAndroidOmx 1.0
-
-Rectangle {
- id: root
- color: "white"
-
- Column {
- width: parent.width
- anchors.verticalCenter: parent.verticalCenter
-
- OmxItem {
- id: omx
-
- width: root.width * 0.5
- height: width / aspect
-
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.margins: 40
- source: "NativeMedia.ts"
-
- property real aspect: sourceWidth / (sourceHeight > 0 ? sourceHeight : 1)
-
- MouseArea {
- anchors.fill: parent
- onClicked: parent.paused = !parent.paused
- }
- }
-
- Text {
- anchors.horizontalCenter: parent.horizontalCenter
- text: "Video size: " + omx.sourceWidth + "x" + omx.sourceHeight
- }
- }
-}
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
deleted file mode 100644
index cb74ee6..0000000
--- a/src/plugins/plugins.pro
+++ /dev/null
@@ -1,3 +0,0 @@
-TEMPLATE = subdirs
-SUBDIRS += sensors
-
diff --git a/src/plugins/sensors/eandroid/eandroid.pro b/src/plugins/sensors/eandroid/eandroid.pro
deleted file mode 100644
index 3b15f74..0000000
--- a/src/plugins/sensors/eandroid/eandroid.pro
+++ /dev/null
@@ -1,30 +0,0 @@
-TARGET = qtsensors_eandroid
-QT = core sensors
-
-PLUGIN_TYPE = sensors
-load(qt_plugin)
-
-LIBS += -lhardware
-
-HEADERS += \
- eandroidambientlightsensor.h \
- eandroidsensordevice.h \
- eandroidbasesensor.h \
- eandroidaccelerometer.h \
- eandroidlight.h \
- eandroidgyroscope.h \
- eandroidmagnetometer.h \
- eandroidrotationsensor.h
-
-SOURCES += \
- main.cpp \
- eandroidambientlightsensor.cpp \
- eandroidsensordevice.cpp \
- eandroidbasesensor.cpp \
- eandroidaccelerometer.cpp \
- eandroidlight.cpp \
- eandroidgyroscope.cpp \
- eandroidmagnetometer.cpp \
- eandroidrotationsensor.cpp
-
-OTHER_FILES = plugin.json
diff --git a/src/plugins/sensors/eandroid/eandroidaccelerometer.cpp b/src/plugins/sensors/eandroid/eandroidaccelerometer.cpp
deleted file mode 100644
index 0d4fa62..0000000
--- a/src/plugins/sensors/eandroid/eandroidaccelerometer.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include <eandroidaccelerometer.h>
-
-EAndroidAccelerometer::EAndroidAccelerometer(int type, QSensor *sensor)
- : EAndroidBaseSensor(type, sensor)
-{
- setReading<QAccelerometerReading>(&m_reading);
-}
-
-EAndroidAccelerometer::~EAndroidAccelerometer()
-{
-}
-
-void EAndroidAccelerometer::processEvent(sensors_event_t &event)
-{
- m_reading.setTimestamp(event.timestamp / 1000);
- m_reading.setX(event.data[0]);
- m_reading.setY(event.data[1]);
- m_reading.setZ(event.data[2]);
- newReadingAvailable();
-}
diff --git a/src/plugins/sensors/eandroid/eandroidaccelerometer.h b/src/plugins/sensors/eandroid/eandroidaccelerometer.h
deleted file mode 100644
index 0062c2c..0000000
--- a/src/plugins/sensors/eandroid/eandroidaccelerometer.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#ifndef EANDROIDACCELEROMETER_H
-#define EANDROIDACCELEROMETER_H
-
-#include <eandroidbasesensor.h>
-
-#include <QtSensors/QAccelerometerReading>
-
-class EAndroidAccelerometer : public EAndroidBaseSensor
-{
- Q_OBJECT
-public:
- EAndroidAccelerometer(int type, QSensor *sensor);
- ~EAndroidAccelerometer();
- void processEvent(sensors_event_t &event);
-
-private:
- QAccelerometerReading m_reading;
-};
-
-#endif // EANDROIDACCELEROMETER_H
diff --git a/src/plugins/sensors/eandroid/eandroidambientlightsensor.cpp b/src/plugins/sensors/eandroid/eandroidambientlightsensor.cpp
deleted file mode 100644
index 10e4bc3..0000000
--- a/src/plugins/sensors/eandroid/eandroidambientlightsensor.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include "eandroidambientlightsensor.h"
-
-EAndroidAmbientLightSensor::EAndroidAmbientLightSensor(int type, QSensor *sensor)
- : EAndroidBaseSensor(type, sensor)
-{
- setReading<QAmbientLightReading>(&m_reading);
-}
-
-EAndroidAmbientLightSensor::~EAndroidAmbientLightSensor()
-{
-}
-
-void EAndroidAmbientLightSensor::processEvent(sensors_event_t &event)
-{
- const int lightLevelLux = event.light;
-
- if (lightLevelLux < 10)
- m_reading.setLightLevel(QAmbientLightReading::Dark);
- else if (lightLevelLux < 80)
- m_reading.setLightLevel(QAmbientLightReading::Twilight);
- else if (lightLevelLux < 400)
- m_reading.setLightLevel(QAmbientLightReading::Light);
- else if (lightLevelLux < 2500)
- m_reading.setLightLevel(QAmbientLightReading::Bright);
- else
- m_reading.setLightLevel(QAmbientLightReading::Sunny);
-
- newReadingAvailable();
-}
diff --git a/src/plugins/sensors/eandroid/eandroidambientlightsensor.h b/src/plugins/sensors/eandroid/eandroidambientlightsensor.h
deleted file mode 100644
index dba24ea..0000000
--- a/src/plugins/sensors/eandroid/eandroidambientlightsensor.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#ifndef EANDROIDAMBIENTLIGHTSENSOR_H
-#define EANDROIDAMBIENTLIGHTSENSOR_H
-
-#include <eandroidbasesensor.h>
-
-#include <QtSensors/QAmbientLightReading>
-
-class EAndroidAmbientLightSensor : public EAndroidBaseSensor
-{
- Q_OBJECT
-public:
- EAndroidAmbientLightSensor(int type, QSensor *sensor);
- ~EAndroidAmbientLightSensor();
- void processEvent(sensors_event_t &event);
-
-private:
- QAmbientLightReading m_reading;
-};
-
-#endif // EANDROIDAMBIENTLIGHTSENSOR_H
diff --git a/src/plugins/sensors/eandroid/eandroidbasesensor.cpp b/src/plugins/sensors/eandroid/eandroidbasesensor.cpp
deleted file mode 100644
index 49ec5e4..0000000
--- a/src/plugins/sensors/eandroid/eandroidbasesensor.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include <eandroidbasesensor.h>
-#include <eandroidsensordevice.h>
-
-EAndroidBaseSensor::EAndroidBaseSensor(int sensorType, QSensor *sensor)
- : QSensorBackend(sensor)
-{
- m_type = sensorType;
- m_isStarted = false;
- EAndroidSensorDevice *device = EAndroidSensorDevice::instance();
- setDescription(device->description(sensorType));
-#if 0 // #### TODO - QTBUG-33293
- qint32 maxRate = device->maxDataRate(sensorType); // convert to Hz
- addDataRate(1, 70);
- addOutputRange(1,55,6);
-#endif
-}
-
-EAndroidBaseSensor::~EAndroidBaseSensor()
-{
- if (m_isStarted)
- stop();
-}
-
-void EAndroidBaseSensor::start()
-{
- EAndroidSensorDevice::instance()->registerListener(m_type, this, sensor()->dataRate());
- m_isStarted = true;
-}
-
-void EAndroidBaseSensor::stop()
-{
- if (m_isStarted) {
- m_isStarted = false;
- EAndroidSensorDevice::instance()->unregisterListener(m_type, this);
- }
-}
-
-void EAndroidBaseSensor::processEvent(sensors_event_t &event)
-{
- Q_UNUSED(event)
-}
diff --git a/src/plugins/sensors/eandroid/eandroidbasesensor.h b/src/plugins/sensors/eandroid/eandroidbasesensor.h
deleted file mode 100644
index 16afebf..0000000
--- a/src/plugins/sensors/eandroid/eandroidbasesensor.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#ifndef EANDROIDBASESENSOR_H
-#define EANDROIDBASESENSOR_H
-
-#include <qsensorbackend.h>
-#include <hardware/sensors.h>
-
-class EAndroidBaseSensor : public QSensorBackend
-{
- Q_OBJECT
-public:
- EAndroidBaseSensor(int sensorType, QSensor *sensor);
- virtual ~EAndroidBaseSensor();
- virtual void start();
- virtual void stop();
- virtual void processEvent(sensors_event_t &event);
-
-private:
- int m_type;
- bool m_isStarted;
-};
-
-#endif // EANDROIDBASESENSOR_H
diff --git a/src/plugins/sensors/eandroid/eandroidgyroscope.cpp b/src/plugins/sensors/eandroid/eandroidgyroscope.cpp
deleted file mode 100644
index 783933f..0000000
--- a/src/plugins/sensors/eandroid/eandroidgyroscope.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include "eandroidgyroscope.h"
-#include <math.h>
-
-EAndroidGyroscope::EAndroidGyroscope(int type, QSensor *sensor)
- : EAndroidBaseSensor(type, sensor)
-{
- setReading<QGyroscopeReading>(&m_reading);
-}
-
-EAndroidGyroscope::~EAndroidGyroscope()
-{
-}
-
-void EAndroidGyroscope::processEvent(sensors_event_t &event)
-{
- m_reading.setTimestamp(event.timestamp / 1000);
- m_reading.setX(event.gyro.x *180/M_PI);
- m_reading.setY(event.gyro.y *180/M_PI);
- m_reading.setZ(event.gyro.z *180/M_PI);
- newReadingAvailable();
-}
-
diff --git a/src/plugins/sensors/eandroid/eandroidgyroscope.h b/src/plugins/sensors/eandroid/eandroidgyroscope.h
deleted file mode 100644
index 96a8005..0000000
--- a/src/plugins/sensors/eandroid/eandroidgyroscope.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#ifndef EANDROIDGYROSCOPE_H
-#define EANDROIDGYROSCOPE_H
-
-#include <eandroidbasesensor.h>
-
-#include <QtSensors/QGyroscopeReading>
-
-class EAndroidGyroscope : public EAndroidBaseSensor
-{
- Q_OBJECT
-public:
- EAndroidGyroscope(int type, QSensor *sensor);
- ~EAndroidGyroscope();
- void processEvent(sensors_event_t &event);
-
-private:
- QGyroscopeReading m_reading;
-};
-
-#endif // EANDROIDGYROSCOPE_H
diff --git a/src/plugins/sensors/eandroid/eandroidlight.cpp b/src/plugins/sensors/eandroid/eandroidlight.cpp
deleted file mode 100644
index a7e9243..0000000
--- a/src/plugins/sensors/eandroid/eandroidlight.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include <eandroidlight.h>
-
-EAndroidLight::EAndroidLight(int type, QSensor *sensor)
- : EAndroidBaseSensor(type, sensor)
-{
- setReading<QLightReading>(&m_reading);
-}
-
-EAndroidLight::~EAndroidLight()
-{
-}
-
-void EAndroidLight::processEvent(sensors_event_t &event)
-{
- m_reading.setTimestamp(event.timestamp / 1000);
- m_reading.setLux(event.light);
- newReadingAvailable();
-}
diff --git a/src/plugins/sensors/eandroid/eandroidlight.h b/src/plugins/sensors/eandroid/eandroidlight.h
deleted file mode 100644
index 75ce1ac..0000000
--- a/src/plugins/sensors/eandroid/eandroidlight.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#ifndef EANDROIDLIGHT_H
-#define EANDROIDLIGHT_H
-
-#include <eandroidbasesensor.h>
-
-#include <QtSensors/QLightReading>
-
-class EAndroidLight : public EAndroidBaseSensor
-{
- Q_OBJECT
-public:
- EAndroidLight(int type, QSensor *sensor);
- ~EAndroidLight();
- void processEvent(sensors_event_t &ev);
-
-private:
- QLightReading m_reading;
-};
-
-#endif // EANDROIDLIGHT_H
diff --git a/src/plugins/sensors/eandroid/eandroidmagnetometer.cpp b/src/plugins/sensors/eandroid/eandroidmagnetometer.cpp
deleted file mode 100644
index 73597b2..0000000
--- a/src/plugins/sensors/eandroid/eandroidmagnetometer.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include "eandroidmagnetometer.h"
-
-EAndroidMagnetometer::EAndroidMagnetometer(int type, QSensor *sensor)
- : EAndroidBaseSensor(type, sensor)
-{
- setReading<QMagnetometerReading>(&m_reading);
-}
-
-EAndroidMagnetometer::~EAndroidMagnetometer()
-{
-}
-
-void EAndroidMagnetometer::processEvent(sensors_event_t &event)
-{
- m_reading.setTimestamp(event.timestamp / 1000);
- // convect micro-Tesla to tesla
- m_reading.setX(event.magnetic.x / 1e6);
- m_reading.setY(event.magnetic.y / 1e6);
- m_reading.setZ(event.magnetic.z / 1e6);
-
- switch (event.magnetic.status) {
- case SENSOR_STATUS_UNRELIABLE:
- m_reading.setCalibrationLevel(0.0);
- break;
- case SENSOR_STATUS_ACCURACY_LOW:
- m_reading.setCalibrationLevel(0.3);
- break;
- case SENSOR_STATUS_ACCURACY_MEDIUM:
- m_reading.setCalibrationLevel(0.6);
- break;
- case SENSOR_STATUS_ACCURACY_HIGH:
- m_reading.setCalibrationLevel(1.0);
- break;
- default:
- break;
- }
-
- newReadingAvailable();
-}
diff --git a/src/plugins/sensors/eandroid/eandroidmagnetometer.h b/src/plugins/sensors/eandroid/eandroidmagnetometer.h
deleted file mode 100644
index 92838b5..0000000
--- a/src/plugins/sensors/eandroid/eandroidmagnetometer.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#ifndef EANDROIDMAGNETOMETER_H
-#define EANDROIDMAGNETOMETER_H
-
-#include <eandroidbasesensor.h>
-
-#include <QtSensors/QMagnetometerReading>
-
-class EAndroidMagnetometer : public EAndroidBaseSensor
-{
- Q_OBJECT
-public:
- EAndroidMagnetometer(int type, QSensor *sensor);
- ~EAndroidMagnetometer();
- void processEvent(sensors_event_t &event);
-
-private:
- QMagnetometerReading m_reading;
-};
-
-#endif // EANDROIDMAGNETOMETER_H
diff --git a/src/plugins/sensors/eandroid/eandroidrotationsensor.cpp b/src/plugins/sensors/eandroid/eandroidrotationsensor.cpp
deleted file mode 100644
index ee0ab7a..0000000
--- a/src/plugins/sensors/eandroid/eandroidrotationsensor.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include "eandroidrotationsensor.h"
-#include <math.h>
-
-EAndroidRotationSensor::EAndroidRotationSensor(int type, QSensor *sensor)
- : EAndroidBaseSensor(type, sensor)
-{
- setReading<QRotationReading>(&m_reading);
-}
-
-EAndroidRotationSensor::~EAndroidRotationSensor()
-{
-}
-
-void EAndroidRotationSensor::processEvent(sensors_event_t &event)
-{
- m_reading.setTimestamp(event.timestamp / 1000);
-
- float rz = -event.data[0] * 180 / M_PI;
- float rx = -event.data[1] * 180 / M_PI;
- float ry = event.data[2] * 180 / M_PI;
-
- m_reading.setFromEuler(rx, ry, rz);
- newReadingAvailable();
-}
diff --git a/src/plugins/sensors/eandroid/eandroidrotationsensor.h b/src/plugins/sensors/eandroid/eandroidrotationsensor.h
deleted file mode 100644
index 79ac239..0000000
--- a/src/plugins/sensors/eandroid/eandroidrotationsensor.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#ifndef EANDROIDROTATIONSENSOR_H
-#define EANDROIDROTATIONSENSOR_H
-
-#include <eandroidbasesensor.h>
-
-#include <QtSensors/QRotationReading>
-
-class EAndroidRotationSensor : public EAndroidBaseSensor
-{
- Q_OBJECT
-public:
- EAndroidRotationSensor(int type, QSensor *sensor);
- ~EAndroidRotationSensor();
- void processEvent(sensors_event_t &event);
-
-private:
- QRotationReading m_reading;
-};
-
-#endif // EANDROIDROTATIONSENSOR_H
diff --git a/src/plugins/sensors/eandroid/eandroidsensordevice.cpp b/src/plugins/sensors/eandroid/eandroidsensordevice.cpp
deleted file mode 100644
index 9b9e03e..0000000
--- a/src/plugins/sensors/eandroid/eandroidsensordevice.cpp
+++ /dev/null
@@ -1,212 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include <eandroidsensordevice.h>
-
-EventReaderThread::EventReaderThread(EAndroidSensorDevice *device) :
- m_device(device)
-{
-}
-
-SensorEventArray* EventReaderThread::lock()
-{
- m_mutex.lock();
- return &m_events;
-}
-
-void EventReaderThread::run()
-{
- static const size_t numEvents = 16;
- sensors_event_t buffer[numEvents];
- int err = 0;
- int n;
- do {
- n = m_device->m_sensorDevice->poll(m_device->m_sensorDevice, buffer, numEvents);
- if (n < 0) {
- qWarning("poll() failed (%s)\n", strerror(-err));
- break;
- }
- m_mutex.lock();
- for (int i = 0 ; i < n ; i++) {
- sensors_event_t& event = buffer[i];
- if (event.version != sizeof(sensors_event_t)) {
- qWarning("incorrect event version (version=%d, expected=%d",
- event.version, sizeof(sensors_event_t));
- break;
- }
- m_events.append(event);
- }
- m_mutex.unlock();
- eventPending();
- } while (true);
-}
-
-EAndroidSensorDevice::EAndroidSensorDevice()
- : m_eventThread(0),
- m_sensorModule(0),
- m_sensorDevice(0),
- m_availableSensorsList(0),
- m_initSuccess(true)
-{
- m_initSuccess = initSensorDevice();
- if (m_initSuccess) {
- m_eventThread = new EventReaderThread(this);
- connect(m_eventThread, SIGNAL(eventPending()), this,
- SLOT(processSensorEvents()), Qt::QueuedConnection);
- } else {
- qWarning("Failed to initialize sensor module. Possibly a missing sensor driver?");
- }
-}
-
-EAndroidSensorDevice* EAndroidSensorDevice::m_instance = 0;
-EAndroidSensorDevice* EAndroidSensorDevice::instance()
-{
- if (!m_instance)
- m_instance = new EAndroidSensorDevice();
- return m_instance;
-}
-
-void EAndroidSensorDevice::registerListener(int type, EAndroidBaseSensor *sensor, int dataRateHz)
-{
- bool startReaderThread = m_listenersHash.isEmpty();
- bool enableSensor = m_listenersHash[type].isEmpty();
- m_listenersHash[type].push_back(sensor);
- if (startReaderThread)
- m_eventThread->start();
- if (enableSensor) {
- setActive(type, true);
- setDelay(type, dataRateHz);
- }
-}
-
-void EAndroidSensorDevice::unregisterListener(int type, EAndroidBaseSensor *sensor)
-{
- m_listenersHash[type].removeOne(sensor);
- bool disableSensor = m_listenersHash[type].isEmpty();
- if (disableSensor)
- m_listenersHash.remove(type);
- bool stopReaderThread = m_listenersHash.isEmpty();
- if (stopReaderThread)
- m_eventThread->quit();
- if (disableSensor)
- setActive(type, false);
-}
-
-int EAndroidSensorDevice::indexForType(int type) const
-{
- for (int i = 0; i < m_availableSensors; ++i)
- if (m_availableSensorsList[i].type == type)
- return i;
- qWarning() << "invalid sensor type: " << type;
- return -1;
-}
-
-void EAndroidSensorDevice::setActive(int type, bool enable)
-{
- for (int i = 0; i < m_availableSensors; i++) {
- if (m_availableSensorsList[i].type == type) {
- int err = m_sensorDevice->activate(m_sensorDevice,
- m_availableSensorsList[i].handle, enable);
- if (err != 0)
- qWarning("activate() for '%s'failed (%s)\n",
- m_availableSensorsList[i].name, strerror(-err));
- }
- }
-}
-
-void EAndroidSensorDevice::setDelay(int type, int dataRateHz) const
-{
- qint64 ns;
- // convert microseconds to nanoseconds
- qint32 maxRateNs = maxDataRate(type) * 1000;
- if (dataRateHz == 0) {
- // if dataRateHz is not set, then we use maxRateNs
- ns = maxRateNs;
- } else {
- // convert Hz to nanoseconds
- ns = 1000000000LL / dataRateHz;
- if (ns > maxRateNs)
- ns = maxRateNs;
- }
- int index = indexForType(type);
- if (index != -1)
- m_sensorDevice->setDelay(m_sensorDevice,
- m_availableSensorsList[index].handle, ns);
-
-}
-
-qint32 EAndroidSensorDevice::maxDataRate(int type) const
-{
- // minDelay - minimum delay allowed between events in microseconds
- int index = indexForType(type);
- if (index != -1)
- return m_availableSensorsList[index].minDelay;
- return 0;
-}
-
-QString EAndroidSensorDevice::description(int type) const
-{
- int index = indexForType(type);
- if (index != -1) {
- QString desc;
- desc.append(m_availableSensorsList[index].name);
- desc.append(QString(" (Vendor:%1) ").arg(m_availableSensorsList[index].vendor));
- return desc;
- }
- return QString();
-}
-
-int EAndroidSensorDevice::availableSensors(sensor_t const** list) const
-{
- if (m_initSuccess)
- return m_sensorModule->get_sensors_list(m_sensorModule, list);
- return 0;
-}
-
-bool EAndroidSensorDevice::initSensorDevice()
-{
- int err = 0;
- err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,
- (hw_module_t const**)&m_sensorModule);
- if (err != 0 || !m_sensorModule) {
- qWarning("hw_get_module() failed (%s)\n", strerror(-err));
- return false;
- }
-
- err = sensors_open(&m_sensorModule->common, &m_sensorDevice);
- if (err != 0 || !m_sensorDevice) {
- qWarning("sensors_open() failed (%s)\n", strerror(-err));
- return false;
- }
-
- m_availableSensors = m_sensorModule->get_sensors_list(m_sensorModule,
- &m_availableSensorsList);
- return true;
-}
-
-void EAndroidSensorDevice::processSensorEvents() const
-{
- SensorEventArray *eventqueue = m_eventThread->lock();
- for (int i = 0; i < eventqueue->size(); i++) {
- sensors_event_t event = eventqueue->at(i);
- foreach (EAndroidBaseSensor *sensorListener, m_listenersHash[event.type])
- sensorListener->processEvent(event);
- }
- eventqueue->clear();
- m_eventThread->unlock();
-}
diff --git a/src/plugins/sensors/eandroid/eandroidsensordevice.h b/src/plugins/sensors/eandroid/eandroidsensordevice.h
deleted file mode 100644
index db4e0f4..0000000
--- a/src/plugins/sensors/eandroid/eandroidsensordevice.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#ifndef EANDROIDSENSORDEVICE_H
-#define EANDROIDSENSORDEVICE_H
-
-#include <eandroidaccelerometer.h>
-#include <eandroidlight.h>
-#include <eandroidambientlightsensor.h>
-#include <eandroidgyroscope.h>
-#include <eandroidmagnetometer.h>
-#include <eandroidrotationsensor.h>
-
-#include <QtCore/QThread>
-#include <QtCore/QMutex>
-#include <QtCore/QReadWriteLock>
-#include <QtCore/QVarLengthArray>
-#include <QtCore/QHash>
-#include <QtCore/QList>
-#include <QtCore/QDebug>
-
-typedef QVarLengthArray<sensors_event_t, 16> SensorEventArray;
-typedef QHash<int, QList<EAndroidBaseSensor *> > ListenersHash;
-
-class EAndroidSensorDevice;
-
-class EventReaderThread : public QThread
-{
- Q_OBJECT
-public:
- EventReaderThread(EAndroidSensorDevice *manager);
- void run();
- SensorEventArray* lock();
- inline void unlock() { m_mutex.unlock(); }
-
-signals:
- void eventPending();
-
-private:
- EAndroidSensorDevice *m_device;
- SensorEventArray m_events;
- QMutex m_mutex;
-};
-
-class EAndroidSensorDevice : public QObject
-{
- Q_OBJECT
-public:
- static EAndroidSensorDevice* instance();
-
- void registerListener(int type, EAndroidBaseSensor *sensor, int dataRateHz);
- void unregisterListener(int type, EAndroidBaseSensor *sensor);
- int availableSensors(sensor_t const** list) const;
- qint32 maxDataRate(int type) const;
- QString description(int type) const;
-
-protected:
- bool initSensorDevice();
- int indexForType(int type) const;
- void setActive(int type, bool enable);
- void setDelay(int type, int dataRateHz) const;
-
-public slots:
- void processSensorEvents() const;
-
-private:
- static EAndroidSensorDevice* m_instance;
- EAndroidSensorDevice();
- EAndroidSensorDevice(const EAndroidSensorDevice &);
- EAndroidSensorDevice& operator=(const EAndroidSensorDevice &);
-
- friend class EventReaderThread;
- EventReaderThread *m_eventThread;
-
- sensors_module_t* m_sensorModule;
- sensors_poll_device_t* m_sensorDevice;
- sensor_t const* m_availableSensorsList;
- int m_availableSensors;
- bool m_initSuccess;
-
- ListenersHash m_listenersHash;
-};
-
-#endif // EANDROIDSENSORDEVICE_H
diff --git a/src/plugins/sensors/eandroid/main.cpp b/src/plugins/sensors/eandroid/main.cpp
deleted file mode 100644
index 8b62a18..0000000
--- a/src/plugins/sensors/eandroid/main.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtSensors module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://www.qt.io/licensing. For further information
-** use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-#include <qsensorplugin.h>
-#include <qsensorbackend.h>
-#include <qsensormanager.h>
-#include <qsensor.h>
-
-#include <eandroidsensordevice.h>
-
-class EAndroidSensorPlugin : public QObject, public QSensorPluginInterface, public QSensorBackendFactory
-{
- Q_OBJECT
- Q_PLUGIN_METADATA(IID "com.qt-project.Qt.QSensorPluginInterface/1.0" FILE "plugin.json")
- Q_INTERFACES(QSensorPluginInterface)
-public:
- void registerSensors()
- {
-#define REGISTER_BACKEND(type, id) \
- QSensorManager::registerBackend(type, id, this); \
-
- sensor_t const* sensors;
- QByteArray id;
- int count = EAndroidSensorDevice::instance()->availableSensors(&sensors);
- for (int i = 0; i < count; i++) {
- id = QByteArray::number(sensors[i].type);
- switch (sensors[i].type) {
- case SENSOR_TYPE_ACCELEROMETER:
- REGISTER_BACKEND(QAccelerometer::type, id)
- break;
- case SENSOR_TYPE_MAGNETIC_FIELD:
- REGISTER_BACKEND(QMagnetometer::type, id)
- break;
- case SENSOR_TYPE_ORIENTATION:
- break;
- case SENSOR_TYPE_GYROSCOPE:
- REGISTER_BACKEND(QGyroscope::type, id)
- break;
- case SENSOR_TYPE_LIGHT:
- REGISTER_BACKEND(QLightSensor::type, id);
- REGISTER_BACKEND(QAmbientLightSensor::type, id);
- break;
- case SENSOR_TYPE_PRESSURE:
- break;
- case SENSOR_TYPE_TEMPERATURE:
- break;
- case SENSOR_TYPE_PROXIMITY:
- break;
- case SENSOR_TYPE_GRAVITY:
- break;
- case SENSOR_TYPE_LINEAR_ACCELERATION:
- break;
- case SENSOR_TYPE_ROTATION_VECTOR:
- REGISTER_BACKEND(QRotationSensor::type, id);
- break;
- case SENSOR_TYPE_RELATIVE_HUMIDITY:
- break;
- case SENSOR_TYPE_AMBIENT_TEMPERATURE:
- break;
- }
- }
-#undef REGISTER_BACKEND
- }
-
- QSensorBackend *createBackend(QSensor *sensor)
- {
- int sensorType = sensor->identifier().toInt();
- switch (sensorType) {
- case SENSOR_TYPE_ACCELEROMETER:
- return new EAndroidAccelerometer(sensorType, sensor);
- case SENSOR_TYPE_MAGNETIC_FIELD:
- return new EAndroidMagnetometer(sensorType, sensor);
- case SENSOR_TYPE_ORIENTATION:
- break;
- case SENSOR_TYPE_GYROSCOPE:
- return new EAndroidGyroscope(sensorType, sensor);
- case SENSOR_TYPE_LIGHT:
- if (sensor->type() == QAmbientLightSensor::type)
- return new EAndroidAmbientLightSensor(sensorType, sensor);
- else if (sensor->type() == QLightSensor::type)
- return new EAndroidLight(sensorType, sensor);
- case SENSOR_TYPE_PRESSURE:
- break;
- case SENSOR_TYPE_TEMPERATURE:
- break;
- case SENSOR_TYPE_PROXIMITY:
- break;
- case SENSOR_TYPE_GRAVITY:
- break;
- case SENSOR_TYPE_LINEAR_ACCELERATION:
- break;
- case SENSOR_TYPE_ROTATION_VECTOR:
- return new EAndroidRotationSensor(sensorType, sensor);
- case SENSOR_TYPE_RELATIVE_HUMIDITY:
- break;
- case SENSOR_TYPE_AMBIENT_TEMPERATURE:
- break;
- default:
- break;
- }
- return 0;
- }
-};
-
-#include "main.moc"
diff --git a/src/plugins/sensors/eandroid/plugin.json b/src/plugins/sensors/eandroid/plugin.json
deleted file mode 100644
index 8a55b3a..0000000
--- a/src/plugins/sensors/eandroid/plugin.json
+++ /dev/null
@@ -1 +0,0 @@
-{ "Keys": [ "notused" ] }
diff --git a/src/plugins/sensors/sensors.pro b/src/plugins/sensors/sensors.pro
deleted file mode 100644
index d02cc99..0000000
--- a/src/plugins/sensors/sensors.pro
+++ /dev/null
@@ -1,3 +0,0 @@
-TEMPLATE = subdirs
-android: SUBDIRS += eandroid
-
diff --git a/src/qconnectivity/main.cpp b/src/qconnectivity/main.cpp
deleted file mode 100644
index d25c42e..0000000
--- a/src/qconnectivity/main.cpp
+++ /dev/null
@@ -1,476 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include <QtCore>
-#include <QtNetwork/QLocalSocket>
-#include <QtNetwork/QLocalServer>
-
-#include <unistd.h>
-#include <cutils/properties.h>
-#include <cutils/sockets.h>
-#include <netutils/dhcp.h>
-#include <netutils/ifc.h>
-
-Q_LOGGING_CATEGORY(B2QT_QCONNECTIVITY, "qt.b2qt.qconnectivity")
-
-// Code values come from android/system/netd/ResponseCode.h
-const int InterfaceChange = 600;
-const char UNIQUE_HOSTNAME[] = "net.hostname";
-// sanity check a renewal time, lower value than
-// this might indicate a badly configured DHCP server
-const int MIN_RENEWAL_TIME_SECS = 300; // 5 min
-
-#define ETH_INTERFACE_HW "eth0"
-#define ETH_INTERFACE_EMULATOR "eth1"
-
-#if Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR < 3
-// this function is defined in android/system/core/libnetutils/dhcp_utils.c
-extern "C" {
-int dhcp_do_request_renew(const char *ifname,
- char *ipaddr,
- char *gateway,
- uint32_t *prefixLength,
- char *dns1,
- char *dns2,
- char *server,
- uint32_t *lease,
- char *vendorInfo);
-}
-#endif
-
-static int q_dhcp_do_request(bool renew,
- const char *ifname,
- char *ipaddr,
- char *gateway,
- uint32_t *prefixLength,
- char *dns1,
- char *dns2,
- char *server,
- uint32_t *lease,
- char *vendorInfo,
- char *domain)
-{
-#if Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR < 3
- if (!renew)
- return dhcp_do_request(ifname, ipaddr, gateway, prefixLength, dns1, dns2, server, lease, vendorInfo);
- return dhcp_do_request_renew(ifname, ipaddr, gateway, prefixLength, dns1, dns2, server, lease, vendorInfo);
-#else
- char *dns[3] = {dns1, dns2, 0};
- char mtu[PROPERTY_VALUE_MAX];
-#if Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR < 4
- if (!renew)
- return dhcp_do_request(ifname, ipaddr, gateway, prefixLength, dns, server, lease, vendorInfo);
- return dhcp_do_request_renew(ifname, ipaddr, gateway, prefixLength, dns, server, lease, vendorInfo);
-#else
- if (!renew)
- return dhcp_do_request(ifname, ipaddr, gateway, prefixLength, dns, server, lease, vendorInfo, domain, mtu);
- return dhcp_do_request_renew(ifname, ipaddr, gateway, prefixLength, dns, server, lease, vendorInfo, domain, mtu);
-#endif
-#endif
-}
-
-
-class LeaseTimer;
-class QConnectivityDaemon : public QObject
-{
- Q_OBJECT
-public:
- QConnectivityDaemon();
-
-protected:
- void setHostnamePropery(const char *interface) const;
- void sendCommand(const char *command) const;
- void handleInterfaceChange(const QList<QByteArray> &message);
- bool startDhcp(bool renew, const char *interface);
- void stopDhcp(const char *interface);
- bool ethernetSupported() const;
- bool isEmulator() const;
-
-protected slots:
- void initNetdConnection();
- void handleNetdEvent();
- void handleRequest();
- void handleNewConnection();
- void sendReply(QLocalSocket *requester, const QByteArray &reply) const;
- void updateLease();
- void handleError(QLocalSocket::LocalSocketError /*socketError*/) const;
-
-private:
- friend class LeaseTimer;
- QLocalSocket *m_netdSocket;
- // currently used to listen for requests from Qt Wifi library,
- // in future can be used also for Bluetooth and etc.
- QLocalServer *m_serverSocket;
- bool m_linkUp;
- LeaseTimer *m_leaseTimer;
- bool m_isEmulator;
- QByteArray m_ethInterface;
- // android initializes services in a separate threads, therefore it is
- // not guaranteed that the netd socket will be ready at the time when qconnectivity
- // is starting up - we try to reconnect again after 2 second intervals. This
- // variable holds the maximum attempt count (chosen arbitrarily).
- int m_attemptCount;
-};
-
-class LeaseTimer : public QTimer
-{
- Q_OBJECT
-public:
- LeaseTimer(QConnectivityDaemon *daemon) : m_daemon(daemon) {}
-
- void setInterface(const QByteArray &interface)
- {
- if (m_ifc.isEmpty()) {
- m_ifc = interface;
- } else {
- // for example when user switches from eth0 to wlan0, we
- // stop DHCP on the previous interface
- if (m_ifc != interface) {
- m_daemon->stopDhcp(m_ifc.constData());
- m_ifc = interface;
- }
- }
- }
-
- QByteArray interface() const { return m_ifc; }
-
-private:
- QConnectivityDaemon *m_daemon;
- QByteArray m_ifc;
-};
-
-QConnectivityDaemon::QConnectivityDaemon()
- : m_netdSocket(0),
- m_serverSocket(0),
- m_linkUp(false),
- m_leaseTimer(0),
- m_isEmulator(isEmulator()),
- m_attemptCount(50)
-{
- QLoggingCategory::setFilterRules(QStringLiteral("qt.b2qt.qconnectivity=true"));
- qCDebug(B2QT_QCONNECTIVITY) << "starting QConnectivityDaemon...";
-
- if (!m_isEmulator) {
- m_ethInterface = ETH_INTERFACE_HW;
- m_leaseTimer = new LeaseTimer(this);
- m_leaseTimer->setSingleShot(true);
- connect(m_leaseTimer, SIGNAL(timeout()), this, SLOT(updateLease()));
-
- int serverFd = socket_local_server("qconnectivity", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
- if (serverFd != -1) {
- m_serverSocket = new QLocalServer(this);
- if (m_serverSocket->listen(serverFd))
- connect(m_serverSocket, SIGNAL(newConnection()), this, SLOT(handleNewConnection()));
- else
- qCWarning(B2QT_QCONNECTIVITY) << "not able to listen on the server socket...";
- } else {
- qCWarning(B2QT_QCONNECTIVITY) << "failed to open qconnectivity server socket";
- }
- } else {
- m_ethInterface = ETH_INTERFACE_EMULATOR;
- }
- initNetdConnection();
-}
-
-bool QConnectivityDaemon::isEmulator() const
-{
- bool isEmulator = false;
- QFile conf("/system/bin/appcontroller.conf");
- if (conf.open(QIODevice::ReadOnly)) {
- QByteArray content = conf.readAll();
- isEmulator = content.contains("platform=emulator");
- conf.close();
- } else {
- qCWarning(B2QT_QCONNECTIVITY) << "Failed to read appcontroller.conf";
- }
- return isEmulator;
-}
-
-void QConnectivityDaemon::initNetdConnection()
-{
- int netdFd = socket_local_client("netd", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
- if (netdFd != -1) {
- qCDebug(B2QT_QCONNECTIVITY) << "connected to netd socket";
- m_netdSocket = new QLocalSocket(this);
- m_netdSocket->setSocketDescriptor(netdFd);
- connect(m_netdSocket, SIGNAL(readyRead()), this, SLOT(handleNetdEvent()));
- connect(m_netdSocket, SIGNAL(error(QLocalSocket::LocalSocketError)),
- this, SLOT(handleError(QLocalSocket::LocalSocketError)));
- } else {
- if (--m_attemptCount != 0)
- QTimer::singleShot(200, this, SLOT(initNetdConnection()));
- else
- qCWarning(B2QT_QCONNECTIVITY) << "failed to connect to netd socket!";
- return;
- }
- if (ethernetSupported()) {
- // down-up sequence generates "linkstate" events, which we can use to setup
- // our daemon on initial startup (device boot) or on daemon restarts
- sendCommand(QByteArray("0 interface setcfg ").append(m_ethInterface).append(" down").constData());
- sendCommand(QByteArray("0 interface setcfg ").append(m_ethInterface).append(" up").constData());
- }
- // disable firewall - this setting seems to be enabled only when using "Always-on VPN"
- // mode on Android phones, see setLockdownTracker() in ConnectivityService.java
- sendCommand("0 firewall disable");
-}
-
-void QConnectivityDaemon::setHostnamePropery(const char *interface) const
-{
- // Setup our unique device name (used as a host name argument for dhcpcd call in
- // dhcp_do_request). On Android device name is set in ConnectivityService.java and
- // the id is generated with the help of SecureRandom.java class. We will use Mac
- // address as a unique hostname.
- char prop_value[PROPERTY_VALUE_MAX];
- property_get(UNIQUE_HOSTNAME, prop_value, NULL);
- if ((prop_value[0] == '\0')) {
- char hwaddr[6];
- memset(hwaddr, 0, sizeof(hwaddr));
- ifc_init();
- if (ifc_get_hwaddr(interface, (void *)hwaddr) == 0) {
- QByteArray macAddress(hwaddr, sizeof(hwaddr));
- property_set(UNIQUE_HOSTNAME, macAddress.toHex().prepend("b2qt-").constData());
- } else {
- qCWarning(B2QT_QCONNECTIVITY) << "failed to get MAC address";
- }
- ifc_close();
- }
-}
-
-void QConnectivityDaemon::sendCommand(const char *command) const
-{
- if (!m_netdSocket) {
- qCDebug(B2QT_QCONNECTIVITY) << "netd socket is not ready!";
- return;
- }
- qCDebug(B2QT_QCONNECTIVITY) << "sending command - " << command;
- // netd expects "\0" terminated commands...
- m_netdSocket->write(command, qstrlen(command) + 1);
- m_netdSocket->flush();
-}
-
-void QConnectivityDaemon::handleInterfaceChange(const QList<QByteArray> &message)
-{
- // Format: "Code Iface linkstate <name> <up/down>"
- if (message.size() < 5)
- return;
-
- if (message.at(2) == "linkstate" && message.at(3) == m_ethInterface) {
- if (message.at(4) == "up") {
- // ethernet cable has been plugged in
- if (!m_linkUp) {
- m_linkUp = true;
- startDhcp(false, m_ethInterface);
- }
- } else {
- // .. plugged out
- if (m_linkUp) {
- m_linkUp = false;
- stopDhcp(m_ethInterface);
- }
- }
- }
-}
-
-bool QConnectivityDaemon::startDhcp(bool renew, const char *interface)
-{
- qCDebug(B2QT_QCONNECTIVITY) << "startDhcp [ renew" << renew << "] "
- << "interface: " << interface;
- setHostnamePropery(interface);
-
- int result = 0;
- char ipaddr[PROPERTY_VALUE_MAX];
- quint32 prefixLength = 0;
- char gateway[PROPERTY_VALUE_MAX];
- char dns1[PROPERTY_VALUE_MAX];
- char dns2[PROPERTY_VALUE_MAX];
- char server[PROPERTY_VALUE_MAX];
- quint32 lease = 0;
- char vendorInfo[PROPERTY_VALUE_MAX];
- char domain[PROPERTY_VALUE_MAX] = {0};
-
- if (renew) {
- result = q_dhcp_do_request(true, interface, ipaddr, gateway, &prefixLength,
- dns1, dns2, server, &lease, vendorInfo, domain);
- } else {
- // stop any existing DHCP daemon before starting new
- dhcp_stop(interface);
- // this uses "ctl.start.*" mechanism to start "dhcpcd" daemon as defined by
- // the device init.rc. Android starts dhcpcd with argument -B which means that
- // we are responsible for renewing a lease before it expires
- ifc_clear_addresses(interface);
- result = q_dhcp_do_request(false, interface, ipaddr, gateway, &prefixLength,
- dns1, dns2, server, &lease, vendorInfo, domain);
- }
-
- bool success = (result == 0) ? true : false;
- if (success) {
- qCDebug(B2QT_QCONNECTIVITY) << "\nipaddr: " << ipaddr << "\nprefixLength: " << prefixLength
- << "\ngateway: " << gateway << "\ndns1: " << dns1 << "\ndns2: " << dns2;
-
- if (!renew) {
- in_addr _ipaddr, _gateway, _dns1, _dns2;
- inet_aton(ipaddr, &_ipaddr);
- inet_aton(gateway, &_gateway);
- inet_aton(dns1, &_dns1);
- inet_aton(dns2, &_dns2);
-
- ifc_configure(interface, _ipaddr.s_addr, prefixLength,
- _gateway.s_addr, _dns1.s_addr, _dns2.s_addr);
-
- // set DNS servers and domain for interface - see NetworkManagementService.java
- QByteArray dnsForInterface("0 resolver setifdns ");
- dnsForInterface.append(interface).append(" ");
- if (domain[0])
- dnsForInterface.append(domain);
- else
- dnsForInterface.append(" ");
- dnsForInterface.append(" ");
- dnsForInterface.append(dns1).append(" ").append(dns2);
- sendCommand(dnsForInterface.constData());
-
- // set default interface for DNS - see NetworkManagementService.java
- sendCommand(QByteArray("0 resolver setdefaultif ").append(interface).constData());
-
- property_set("net.dns1", dns1);
- property_set("net.dns2", dns2);
- }
-
- if (!m_isEmulator && lease >= 0) {
- if (lease < MIN_RENEWAL_TIME_SECS) {
- qCWarning(B2QT_QCONNECTIVITY) << "DHCP server proposes lease time " << lease
- << "seconds. We will use" << MIN_RENEWAL_TIME_SECS << " seconds instead.";
- lease = MIN_RENEWAL_TIME_SECS;
- }
- // update lease when 48% of lease time has elapsed
- if (m_leaseTimer->isActive())
- m_leaseTimer->stop();
- m_leaseTimer->setInterface(interface);
- m_leaseTimer->start(lease * 480);
- }
- } else {
- qCWarning(B2QT_QCONNECTIVITY, "DHCP request failed - %s", dhcp_get_errmsg());
- if (renew) {
- // If it fails to renew a lease (faulty server, proxy?) we re-connect.
- // Some users might prefer to use expired lease over having interrupt
- // in network connection
- if (qEnvironmentVariableIsSet("QT_USE_EXPIRED_LEASE"))
- return true;
- qCDebug(B2QT_QCONNECTIVITY) << "attempting to re-connect...";
- stopDhcp(interface);
- startDhcp(false, interface);
- }
- }
- return success;
-}
-
-void QConnectivityDaemon::stopDhcp(const char *interface)
-{
- qCDebug(B2QT_QCONNECTIVITY) << "stopDhcp: " << interface;
- ifc_clear_addresses(interface);
- dhcp_stop(interface);
- if (!m_isEmulator && m_leaseTimer->isActive())
- m_leaseTimer->stop();
-}
-
-bool QConnectivityDaemon::ethernetSupported() const
-{
- // standard linux kernel path
- return QDir().exists(QString("/sys/class/net/").append(m_ethInterface));
-}
-
-void QConnectivityDaemon::handleNetdEvent()
-{
- QByteArray data = m_netdSocket->readAll();
- qCDebug(B2QT_QCONNECTIVITY) << "netd event: " << data;
- if (data.endsWith('\0'))
- data.chop(1);
-
- QList<QByteArray> message = data.split(' ');
- int code = message.at(0).toInt();
- switch (code) {
- case InterfaceChange:
- handleInterfaceChange(message);
- break;
- default:
- break;
- }
-}
-
-void QConnectivityDaemon::handleRequest()
-{
- // Format: "interface <connect/disconnect>"
- QLocalSocket *requester = qobject_cast<QLocalSocket *>(QObject::sender());
- if (requester->canReadLine()) {
- QByteArray request = requester->readLine(requester->bytesAvailable());
-
- qCDebug(B2QT_QCONNECTIVITY) << "received a request: " << request;
- QList<QByteArray> cmd = request.split(' ');
- if (cmd.size() < 2)
- return;
-
- QByteArray interface = cmd.at(0);
- if (cmd.at(1) == "connect") {
- QByteArray reply;
- if (startDhcp(false, interface.constData()))
- reply = "success";
- else
- reply = "failed";
- sendReply(requester, reply);
- } else {
- stopDhcp(interface.constData());
- }
- }
-}
-
-void QConnectivityDaemon::handleNewConnection()
-{
- QLocalSocket *requester = m_serverSocket->nextPendingConnection();
- connect(requester, SIGNAL(readyRead()), this, SLOT(handleRequest()));
- connect(requester, SIGNAL(disconnected()), requester, SLOT(deleteLater()));
-}
-
-void QConnectivityDaemon::sendReply(QLocalSocket *requester, const QByteArray &reply) const
-{
- QByteArray r = reply;
- r.append("\n");
- requester->write(r.constData(), r.length());
- requester->flush();
- requester->disconnectFromServer();
-}
-
-void QConnectivityDaemon::updateLease()
-{
- qCDebug(B2QT_QCONNECTIVITY) << "updating lease";
- startDhcp(true, m_leaseTimer->interface().constData());
-}
-
-void QConnectivityDaemon::handleError(QLocalSocket::LocalSocketError /*socketError*/) const
-{
- qCWarning(B2QT_QCONNECTIVITY) << "QLocalSocket::LocalSocketError";
-}
-
-int main(int argc, char *argv[])
-{
- QCoreApplication a(argc, argv);
-
- QConnectivityDaemon connectivityDaemon;
-
- return a.exec();
-}
-
-#include "main.moc"
diff --git a/src/qconnectivity/qconnectivity.pro b/src/qconnectivity/qconnectivity.pro
deleted file mode 100644
index df3b366..0000000
--- a/src/qconnectivity/qconnectivity.pro
+++ /dev/null
@@ -1,13 +0,0 @@
-QT += core network
-QT -= gui
-
-TARGET = qconnectivity
-CONFIG += console
-CONFIG -= app_bundle
-
-TEMPLATE = app
-
-LIBS += -lcutils -lnetutils
-SOURCES += main.cpp
-
-load(qt_tool)
diff --git a/src/qt_hw_init/main.cpp b/src/qt_hw_init/main.cpp
deleted file mode 100644
index 15cc807..0000000
--- a/src/qt_hw_init/main.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include "b2qtdevice.h"
-
-int main(int, char *[])
-{
- B2QtDevice device;
-
- device.initAudio();
-
- device.setDisplayBrightness(255);
-
- return 0;
-}
diff --git a/src/qt_hw_init/qt_hw_init.pro b/src/qt_hw_init/qt_hw_init.pro
deleted file mode 100644
index 4784926..0000000
--- a/src/qt_hw_init/qt_hw_init.pro
+++ /dev/null
@@ -1,8 +0,0 @@
-TEMPLATE = app
-TARGET = qt_hw_init
-QT -= gui
-QT += b2qtutils
-
-SOURCES += main.cpp
-
-load(qt_tool)
diff --git a/src/src.pro b/src/src.pro
index a0e42dd..ebe58b5 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -4,9 +4,4 @@ SUBDIRS += \
utils \
wifi \
imports \
- doc \
- plugins \
- b2qt-update-util
-
-
-android: SUBDIRS += doppelganger qt_hw_init qconnectivity
+ doc
diff --git a/src/utils/b2qtdevice.cpp b/src/utils/b2qtdevice.cpp
index 460b4da..85006f8 100644
--- a/src/utils/b2qtdevice.cpp
+++ b/src/utils/b2qtdevice.cpp
@@ -28,13 +28,6 @@
#include <QTimer>
#include <QtCore/qmath.h>
-#ifdef Q_OS_ANDROID_NO_SDK
-#include <cutils/properties.h>
-#include <hardware/lights.h>
-#include <media/AudioSystem.h>
-#include <utils/String8.h>
-#endif
-
// When we can't query directly, at least remember what we have set it to
static quint8 knownBrightness = 255;
@@ -127,27 +120,6 @@ static void initLightDevices()
bool B2QtDevice::setDisplayBrightness(int v)
{
quint8 value = qBound(0, v, 255);
-#ifdef Q_OS_ANDROID_NO_SDK
- const struct hw_module_t* module = 0;
- if (hw_get_module(LIGHTS_HARDWARE_MODULE_ID, &module))
- return false;
- if (!module || !module->methods || !module->methods->open)
- return false;
-
- struct light_device_t* device = 0;
- if (module->methods->open(module, LIGHT_ID_BACKLIGHT, (struct hw_device_t**)&device))
- return false;
- if (!device || !device->set_light || !device->common.close)
- return false;
-
- struct light_state_t state;
- memset(&state, 0, sizeof(light_state_t));
- state.color = 0xff000000 | (value << 16) | (value << 8) | value;
- if (!device->set_light(device, &state))
- return false;
-
- device->common.close(&device->common);
-#else
initLightDevices();
for (int i = 0; i < lightDevices.size(); i++) {
LightDevice &ld = lightDevices[i];
@@ -159,7 +131,6 @@ bool B2QtDevice::setDisplayBrightness(int v)
devFile.write(QByteArray::number(newVal));
ld.value = value;
}
-#endif
knownBrightness = value;
return true;
}
@@ -171,18 +142,7 @@ bool B2QtDevice::setDisplayBrightness(int v)
*/
int B2QtDevice::displayBrightness() const
{
-#ifdef Q_OS_ANDROID_NO_SDK
- QFile sysFile(QStringLiteral("/sys/class/leds/lcd-backlight/brightness"));
- if (sysFile.open(QIODevice::ReadOnly | QIODevice::Unbuffered)) {
- bool ok = false;
- int sysVal = sysFile.read(3).simplified().toInt(&ok);
- if (ok)
- knownBrightness = qBound(0, sysVal, 255);
- }
-#else
initLightDevices();
-#endif
-
return knownBrightness;
}
@@ -210,14 +170,7 @@ QString B2QtDevice::getIPAddress() const
QString B2QtDevice::hostname() const
{
QString name;
-#ifdef Q_OS_ANDROID_NO_SDK
- char prop_value[PROPERTY_VALUE_MAX];
- int len = property_get("net.hostname", prop_value, 0);
- if (len)
- name = QString::fromLocal8Bit(prop_value, len);
-#else
name = QHostInfo::localHostName();
-#endif
return name;
}
@@ -227,9 +180,6 @@ QString B2QtDevice::hostname() const
*/
bool B2QtDevice::setHostname(const QString &name)
{
-#ifdef Q_OS_ANDROID_NO_SDK
- property_set("net.hostname", name.toLocal8Bit().constData());
-#else
QByteArray lname = name.toLocal8Bit();
if (::sethostname(lname.constData(), lname.length())) {
qWarning("Could not set system hostname");
@@ -243,7 +193,7 @@ bool B2QtDevice::setHostname(const QString &name)
}
file.write(lname.append('\n'));
file.close();
-#endif
+
emit hostnameChanged(name);
return true;
}
@@ -255,17 +205,7 @@ bool B2QtDevice::setHostname(const QString &name)
*/
void B2QtDevice::setMasterVolume(int volume)
{
-#ifdef Q_OS_ANDROID_NO_SDK
- android::status_t rc;
- volume = qBound(0, volume, 100);
- rc = android::AudioSystem::setMasterVolume(android::AudioSystem::linearToLog(volume));
- if (rc != android::NO_ERROR)
- qWarning() << Q_FUNC_INFO << "Error while setting audio properties.";
- else
- emit masterVolumeChanged(volume);
-#else
Q_UNUSED(volume)
-#endif
}
@@ -275,194 +215,19 @@ void B2QtDevice::setMasterVolume(int volume)
*/
int B2QtDevice::masterVolume() const
{
- float volume = 0;
-#ifdef Q_OS_ANDROID_NO_SDK
- android::status_t rc;
- rc = android::AudioSystem::getMasterVolume(&volume);
- if (rc != android::NO_ERROR)
- qWarning() << Q_FUNC_INFO << "Error while getting audio properties.";
-#endif
- return qBound(0, qRound(volume), 100);
-}
-
-#ifdef Q_OS_ANDROID_NO_SDK
-// Android audio handling
-
-enum AudioOrientation {
- LandscapeAudioOrientation,
- PortraitAudioOrientation,
- SquareAudioOrientation,
- UndefinedAudioOrientation,
-};
-
-enum AudioStreamType {
- DefaultAudioStream = -1,
- VoiceCallAudioStream = 0,
- SystemAudioStream = 1,
- RingAudioStream = 2,
- MusicAudioStream = 3,
- AlarmAudioStream = 4,
- NotificationAudioStream = 5,
- BluetoothAudioStream = 6,
- EnforcedAudibleAudioStream = 7,
- DTMFAudioStream = 8,
- TTSAudioStream = 9
-};
-
-
-/*
- \enum AudioStreamType
- \value DefaultAudioStream
- The default audio stream
-
- \value VoiceCallAudioStream
- The audio stream for phone calls
-
- \value SystemAudioStream
- The audio stream for system sounds
-
- \value RingAudioStream
- The audio stream for the phone ring
-
- \value AlarmAudioStream
- The audio stream for alarms
-
- \value NotificationAudioStream
- The audio stream for notifications
-
- \value BluetoothAudioStream
- The audio stream for audio transmitted over bluetooth
-
- \value EnforcedAudibleAudioStream
- Sounds that cannot be muted by user and must be routed to speaker
-
- \value DTMFAudioStream
- The audio stream for DTMF Tones
-
- \value TTSAudioStream
- The audio stream for text-to-speech
-*/
-
-/*
- * Sets the volume for a specific audio \a stream type to \a volume.
- * The volume can range from 0 to 100 and is linear.
- * All streams of the specified type will be affected.
- *
- * \sa setMasterVolume()
- * \sa setStreamMute()
- */
-void setStreamVolume(AudioStreamType streamType, int volume)
-{
- android::status_t rc;
- volume = qBound(0, volume, 100);
- rc = android::AudioSystem::setStreamVolume(audio_stream_type_t(streamType),
- android::AudioSystem::linearToLog(volume), 0);
- if (rc != android::NO_ERROR)
- qWarning() << Q_FUNC_INFO << "Error while setting audio properties.";
-}
-
-/*
- * Mutes all audio \a streams of type \a streamType.
- *
- * \sa setStreamVolume()
- * \sa setMasterMute()
- */
-void setStreamMute(AudioStreamType streamType, bool mute)
-{
- android::status_t rc;
- rc = android::AudioSystem::setStreamMute(audio_stream_type_t(streamType), mute);
- if (rc != android::NO_ERROR)
- qWarning() << Q_FUNC_INFO << "Error while setting audio properties.";
-}
-
-void setOrientationForAudioSystem(AudioOrientation orientation)
-{
- QString orientationString = QStringLiteral("undefined");
- switch (orientation) {
- case LandscapeAudioOrientation:
- orientationString = QStringLiteral("landscape");
- break;
- case PortraitAudioOrientation:
- orientationString = QStringLiteral("portrait");
- break;
- case SquareAudioOrientation:
- orientationString = QStringLiteral("square");
- break;
- default:
- break;
- }
- android::AudioSystem::setParameters(0, android::String8(QStringLiteral("orientation=%2")
- .arg(orientationString).toLatin1().constData()));
+ return 0;
}
/*!
- * Sets the master mute to \a mute. Setting it to true will disable all
- * sounds on the device.
- *
- * \sa setMasterVolume()
- * \sa setStreamMute()
- */
-void setMasterMute(bool mute)
-{
-
- android::status_t rc;
- rc = android::AudioSystem::setMasterMute(mute);
- if (rc != android::NO_ERROR)
- qWarning() << Q_FUNC_INFO << "Error while setting audio properties.";
-}
-
-bool masterMute()
-{
- bool mute = false;
- android::status_t rc;
- rc = android::AudioSystem::getMasterMute(&mute);
- if (rc != android::NO_ERROR)
- qWarning() << Q_FUNC_INFO << "Error while getting audio properties.";
- return mute;
-}
-
-float streamVolume(AudioStreamType stream)
-{
- float volume = NAN;
- android::status_t rc;
- rc = android::AudioSystem::getStreamVolume(audio_stream_type_t(stream), &volume, 0);
- if (rc != android::NO_ERROR)
- qWarning() << Q_FUNC_INFO << "Error while getting audio properties.";
- return volume;
-}
-
-bool streamMute(AudioStreamType stream)
-{
- bool mute = false;
- android::status_t rc;
- rc = android::AudioSystem::getStreamMute(audio_stream_type_t(stream), &mute);
- if (rc != android::NO_ERROR)
- qWarning() << Q_FUNC_INFO << "Error while getting audio properties.";
- return mute;
-}
-
-#endif
-
-/*!
* Initializes the audio subsystem, setting the volume to max.
* This is done during system startup, so there is normally no need to call this function from applications.
*/
void B2QtDevice::initAudio()
{
-#ifdef Q_OS_ANDROID_NO_SDK
- // Set the audio orientation to something to force the HW driver to reconfigure
- // audio routing (workaround for bug on Nexus 7)
- setOrientationForAudioSystem(LandscapeAudioOrientation);
- setMasterVolume(100);
- setMasterMute(false);
- setStreamVolume(SystemAudioStream, 100);
- setStreamVolume(MusicAudioStream, 100);
- setStreamVolume(NotificationAudioStream, 100);
- setStreamVolume(EnforcedAudibleAudioStream, 100);
-#endif
}
+
class PhysicalScreenSize : public QObject
{
Q_OBJECT
diff --git a/src/utils/utils.pro b/src/utils/utils.pro
index 13287d5..a9f6041 100644
--- a/src/utils/utils.pro
+++ b/src/utils/utils.pro
@@ -9,8 +9,6 @@ QT = core network
MODULE = b2qtutils
load(qt_module)
-android: LIBS += -lmedia -lhardware -lcutils -lutils
-
HEADERS += \
$$PWD/b2qtdevice.h
diff --git a/src/wifi/qwificontroller.cpp b/src/wifi/qwificontroller.cpp
index 7b8be80..61f5761 100644
--- a/src/wifi/qwificontroller.cpp
+++ b/src/wifi/qwificontroller.cpp
@@ -18,113 +18,17 @@
****************************************************************************/
#include "qwificontroller_p.h"
#include "qwifimanager_p.h"
+#include "qwifisupplicant_p.h"
#include "qwifidevice.h"
+#include <sys/types.h>
+#include <signal.h>
+
#include <QtCore/QCoreApplication>
#include <QtCore/QProcess>
#include <QtCore/QByteArray>
#include <QtCore/QFile>
-#ifdef Q_OS_ANDROID_NO_SDK
-#include <QtNetwork/QLocalSocket>
-#include <cutils/sockets.h>
-#include <unistd.h>
-#endif
-
-#ifdef Q_OS_ANDROID_NO_SDK
-/*
- * Workaround API differences between Android versions
- */
-int q_wifi_start_supplicant()
-{
-#if Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR < 1
- return wifi_start_supplicant();
-#else
- return wifi_start_supplicant(0);
-#endif
-}
-
-int q_wifi_stop_supplicant()
-{
-#if Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR < 1
- return wifi_stop_supplicant();
-#else
- return wifi_stop_supplicant(0);
-#endif
-}
-
-int q_wifi_connect_to_supplicant(const char *ifname)
-{
-#if Q_ANDROID_VERSION_MAJOR == 4 && (Q_ANDROID_VERSION_MINOR < 4 && Q_ANDROID_VERSION_MINOR >= 1)
- return wifi_connect_to_supplicant(ifname);
-#else
- Q_UNUSED(ifname);
- return wifi_connect_to_supplicant();
-#endif
-}
-
-void q_wifi_close_supplicant_connection(const char *ifname)
-{
-#if Q_ANDROID_VERSION_MAJOR == 4 && (Q_ANDROID_VERSION_MINOR < 4 && Q_ANDROID_VERSION_MINOR >= 1)
- wifi_close_supplicant_connection(ifname);
-#else
- Q_UNUSED(ifname);
- wifi_close_supplicant_connection();
-#endif
-}
-
-int q_wifi_wait_for_event(const char *ifname, char *buf, size_t len)
-{
-#if Q_ANDROID_VERSION_MAJOR == 4 && (Q_ANDROID_VERSION_MINOR < 4 && Q_ANDROID_VERSION_MINOR >= 1)
- return wifi_wait_for_event(ifname, buf, len);
-#else
- Q_UNUSED(ifname);
- return wifi_wait_for_event(buf, len);
-#endif
-}
-
-int q_wifi_command(const char *ifname, const char *command, char *reply, size_t *reply_len)
-{
-#if Q_ANDROID_VERSION_MAJOR == 4 && (Q_ANDROID_VERSION_MINOR < 4 && Q_ANDROID_VERSION_MINOR >= 1)
- return wifi_command(ifname, command, reply, reply_len);
-#else
- Q_UNUSED(ifname);
- return wifi_command(command, reply, reply_len);
-#endif
-}
-
-/*
- * This function is borrowed from /system/core/libnetutils/dhcp_utils.c
- *
- * Wait for a system property to be assigned a specified value.
- * If desired_value is NULL, then just wait for the property to
- * be created with any value. maxwait is the maximum amount of
- * time in seconds to wait before giving up.
- */
-const int NAP_TIME = 200; // wait for 200ms at a time when polling for property values
-int wait_for_property(const char *name, const char *desired_value, int maxwait)
-{
- char value[PROPERTY_VALUE_MAX] = {'\0'};
- int maxnaps = (maxwait * 1000) / NAP_TIME;
-
- if (maxnaps < 1) {
- maxnaps = 1;
- }
-
- while (maxnaps-- > 0) {
- usleep(NAP_TIME * 1000);
- if (property_get(name, value, NULL)) {
- if (desired_value == NULL ||
- strcmp(value, desired_value) == 0) {
- return 0;
- }
- }
- }
- return -1; /* failure */
-}
-
-#endif // Q_OS_ANDROID_NO_SDK
-
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(B2QT_WIFI, "qt.b2qt.wifi")
@@ -135,7 +39,6 @@ public:
QWifiEventThread(QWifiController *controller)
: m_controller(controller)
{
- m_interface = QWifiDevice::wifiInterfaceName();
}
void run() {
@@ -143,7 +46,7 @@ public:
QWifiEvent *event = 0;
char buffer[2048];
forever {
- int size = q_wifi_wait_for_event(m_interface, buffer, sizeof(buffer) - 1);
+ int size = m_controller->supplicant()->waitForEvent(buffer, sizeof(buffer) - 1);
if (size > 0) {
buffer[size] = 0;
event = 0;
@@ -174,7 +77,6 @@ public:
private:
QWifiController *m_controller;
- QByteArray m_interface;
};
@@ -182,46 +84,22 @@ QWifiController::QWifiController(QWifiManager *manager, QWifiManagerPrivate *man
m_manager(manager),
m_managerPrivate(managerPrivate),
m_exitEventThread(false),
-#ifdef Q_OS_ANDROID_NO_SDK
- m_qcSocket(0),
-#endif
- m_eventThread(0)
+ m_interface(QWifiDevice::wifiInterfaceName()),
+ m_eventThread(new QWifiEventThread(this)),
+ m_supplicant(new QWifiSupplicant(this))
{
- m_interface = QWifiDevice::wifiInterfaceName();
- m_eventThread = new QWifiEventThread(this);
-
qRegisterMetaType<QWifiManager::BackendState>("QWifiManager::BackendState");
-#ifdef Q_OS_ANDROID_NO_SDK
- qRegisterMetaType<QAbstractSocket::SocketState>("QAbstractSocket::SocketState");
-#endif
}
QWifiController::~QWifiController()
{
exitWifiEventThread();
delete m_eventThread;
-#ifdef Q_OS_ANDROID_NO_SDK
- delete m_qcSocket;
-#endif
-}
-
-void QWifiController::allocateOnThisThread()
-{
-#ifdef Q_OS_ANDROID_NO_SDK
- m_qcSocket = new QLocalSocket;
- int qcFd = socket_local_client("qconnectivity", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
- if (qcFd != -1) {
- m_qcSocket->setSocketDescriptor(qcFd);
- } else {
- qCWarning(B2QT_WIFI) << "failed to get file descriptor of a qconnectivity socket!";
- }
-#endif
}
void QWifiController::run()
{
qCDebug(B2QT_WIFI) << "running wifi backend controller thread";
- allocateOnThisThread();
Method method;
forever {
m_methodsMutex.lock();
@@ -249,7 +127,7 @@ void QWifiController::run()
}
}
-void QWifiController::call(Method method)
+void QWifiController::asyncCall(Method method)
{
QMutexLocker locker(&m_methodsMutex);
m_methods.append(method);
@@ -260,23 +138,15 @@ void QWifiController::initializeBackend()
{
qCDebug(B2QT_WIFI) << "initializing wifi backend";
emit backendStateChanged(QWifiManager::Initializing);
- bool initFailed = false;
-#ifdef Q_OS_ANDROID_NO_SDK
- qCDebug(B2QT_WIFI) << "initialize driver";
- if (!(is_wifi_driver_loaded() || wifi_load_driver() == 0)) {
- qCWarning(B2QT_WIFI) << "failed to load a driver";
- initFailed = true;
- }
-#else
qCDebug(B2QT_WIFI) << "run ifconfig (up)";
QProcess ifconfig;
ifconfig.start(QStringLiteral("ifconfig"), QStringList() << QLatin1String(m_interface) << QStringLiteral("up"));
ifconfig.waitForFinished();
+ bool initFailed = false;
if (ifconfig.exitStatus() != QProcess::NormalExit && ifconfig.exitCode() != 0) {
qCWarning(B2QT_WIFI) << "failed to bring up wifi interface!";
initFailed = true;
}
-#endif
if (!initFailed && resetSupplicantSocket()) {
qCDebug(B2QT_WIFI) << "wifi backend started successfully";
emit backendStateChanged(QWifiManager::Running);
@@ -289,22 +159,16 @@ bool QWifiController::resetSupplicantSocket()
{
qCDebug(B2QT_WIFI) << "reset supplicant socket";
exitWifiEventThread();
- if (q_wifi_stop_supplicant() < 0)
+ if (!m_supplicant->stopSupplicant())
qCWarning(B2QT_WIFI) << "failed to stop supplicant!";
- q_wifi_close_supplicant_connection(m_interface);
+ m_supplicant->closeSupplicantConnection();
qCDebug(B2QT_WIFI) << "start supplicant";
- if (q_wifi_start_supplicant() != 0) {
+ if (!m_supplicant->startSupplicant()) {
qCWarning(B2QT_WIFI) << "failed to start a supplicant!";
return false;
}
-#ifdef Q_OS_ANDROID_NO_SDK
- if (wait_for_property("init.svc.wpa_supplicant", "running", 5) < 0) {
- qCWarning(B2QT_WIFI) << "timed out waiting for supplicant to start!";
- return false;
- }
-#endif
qCDebug(B2QT_WIFI) << "connect to supplicant";
- if (q_wifi_connect_to_supplicant(m_interface) != 0) {
+ if (!m_supplicant->connectToSupplicant()) {
qCWarning(B2QT_WIFI) << "failed to connect to a supplicant!";
return false;
}
@@ -317,17 +181,17 @@ void QWifiController::terminateBackend()
qCDebug(B2QT_WIFI) << "terminating wifi backend";
emit backendStateChanged(QWifiManager::Terminating);
exitWifiEventThread();
- if (q_wifi_stop_supplicant() < 0)
+ if (!m_supplicant->stopSupplicant())
qCWarning(B2QT_WIFI) << "failed to stop supplicant!";
- q_wifi_close_supplicant_connection(m_interface);
-#ifndef Q_OS_ANDROID_NO_SDK
+ m_supplicant->closeSupplicantConnection();
+
qCDebug(B2QT_WIFI) << "run ifconfig (down)";
QProcess ifconfig;
ifconfig.start(QStringLiteral("ifconfig"), QStringList() << QLatin1String(m_interface) << QStringLiteral("down"));
ifconfig.waitForFinished();
if (ifconfig.exitStatus() != QProcess::NormalExit && ifconfig.exitCode() != 0)
qCWarning(B2QT_WIFI) << "failed to bring down wifi interface!";
-#endif
+
stopDhcp();
qCDebug(B2QT_WIFI) << "wifi backend stopped successfully";
emit backendStateChanged(QWifiManager::NotRunning);
@@ -349,66 +213,30 @@ void QWifiController::exitWifiEventThread()
}
}
-#ifdef Q_OS_ANDROID_NO_SDK
-bool QWifiController::getQConnectivityReply()
-{
- bool arrived = false;
- if (m_qcSocket->canReadLine()) {
- arrived = true;
- QByteArray received = m_qcSocket->readLine(m_qcSocket->bytesAvailable());
- if (received != "success" && received != "failed") {
- qCWarning(B2QT_WIFI) << "unknown message: " << received;
- received = "failed";
- }
- emit dhcpRequestFinished(QLatin1String(received));
- }
- return arrived;
-}
-#else
void QWifiController::killDhcpProcess(const QString &path) const
{
QFile pidFile(path);
- if (pidFile.exists()) {
- pidFile.open(QIODevice::ReadOnly);
- QByteArray pid = pidFile.readAll();
- QProcess kill;
- kill.start(QStringLiteral("kill"), QStringList() << QLatin1String(pid.trimmed()));
- kill.waitForFinished();
- if (kill.exitStatus() != QProcess::NormalExit && kill.exitCode() != 0)
- qCWarning(B2QT_WIFI) << "killing dhcp process failed!";
+ if (!pidFile.exists())
+ return;
+
+ if (!pidFile.open(QIODevice::ReadOnly)) {
+ qCWarning(B2QT_WIFI) << "could not open pid file: " << path;
+ return;
+ }
+
+ bool ok;
+ int pid = pidFile.readAll().trimmed().toInt(&ok);
+ if (!ok) {
+ qCWarning(B2QT_WIFI) << "pid is not a number!";
+ return;
}
- pidFile.close();
+
+ kill(pid, 9);
}
-#endif
void QWifiController::acquireIPAddress()
{
qCDebug(B2QT_WIFI, "acquireIPAddress");
-#ifdef Q_OS_ANDROID_NO_SDK
- QByteArray request = m_interface + " connect\n";
- m_qcSocket->abort();
- m_qcSocket->connectToServer(QStringLiteral(ANDROID_SOCKET_DIR "/qconnectivity"));
- bool timeout = false;
- if (m_qcSocket->waitForConnected()) {
- m_qcSocket->write(request, request.length());
- m_qcSocket->flush();
- do {
- if (m_qcSocket->waitForReadyRead()) {
- if (getQConnectivityReply())
- break;
- } else {
- timeout = true;
- qCWarning(B2QT_WIFI) << "waiting a message from qconnectivity timed out!";
- break;
- }
- } while (true);
- } else {
- timeout = true;
- qCWarning(B2QT_WIFI) << "connecting to qconnectivity server socket timed out!";
- }
- if (timeout)
- emit dhcpRequestFinished(QStringLiteral("failed"));
-#else
QString filePath = QLatin1String("/var/run/udhcpc." + m_interface + ".pid");
killDhcpProcess(filePath);
QStringList args;
@@ -426,26 +254,13 @@ void QWifiController::acquireIPAddress()
status = QLatin1String("failed");
emit dhcpRequestFinished(status);
-#endif
}
void QWifiController::stopDhcp() const
{
qCDebug(B2QT_WIFI, "stopDhcp");
-#ifdef Q_OS_ANDROID_NO_SDK
- QByteArray request = m_interface + " disconnect\n";
- m_qcSocket->abort();
- m_qcSocket->connectToServer(QStringLiteral(ANDROID_SOCKET_DIR "/qconnectivity"));
- if (m_qcSocket->waitForConnected()) {
- m_qcSocket->write(request, request.length());
- m_qcSocket->flush();
- } else {
- qCWarning(B2QT_WIFI) << "connecting to qconnectivity server socket timed out!";
- }
-#else
QString filePath = QLatin1String("/var/run/udhcpc." + m_interface + ".pid");
killDhcpProcess(filePath);
-#endif
}
QT_END_NAMESPACE
diff --git a/src/wifi/qwificontroller_p.h b/src/wifi/qwificontroller_p.h
index 185cff9..45751fa 100644
--- a/src/wifi/qwificontroller_p.h
+++ b/src/wifi/qwificontroller_p.h
@@ -28,27 +28,10 @@
#include <QtCore/QWaitCondition>
#include <QtCore/QLoggingCategory>
-#ifdef Q_OS_ANDROID_NO_SDK
-#include <hardware_legacy/wifi.h>
-#include <cutils/properties.h>
-#else
-#include "qwifielinux_p.h"
-#endif
-
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(B2QT_WIFI)
-#ifdef Q_OS_ANDROID_NO_SDK
-int q_wifi_start_supplicant();
-int q_wifi_stop_supplicant();
-int q_wifi_connect_to_supplicant(const char *ifname);
-void q_wifi_close_supplicant_connection(const char *ifname);
-int q_wifi_wait_for_event(const char *ifname, char *buf, size_t len);
-int q_wifi_command(const char *ifname, const char *command, char *reply, size_t *reply_len);
-int wait_for_property(const char *name, const char *desired_value, int maxwait);
-#endif
-
const QEvent::Type WIFI_SCAN_RESULTS = (QEvent::Type) (QEvent::User + 2001);
const QEvent::Type WIFI_CONNECTED = (QEvent::Type) (QEvent::User + 2002);
const QEvent::Type WIFI_HANDSHAKE_FAILED = (QEvent::Type) (QEvent::User + 2003);
@@ -58,9 +41,7 @@ const QEvent::Type WIFI_DISCONNECTED = (QEvent::Type) (QEvent::User + 2005);
class QWifiManager;
class QWifiManagerPrivate;
class QWifiEventThread;
-#ifdef Q_OS_ANDROID_NO_SDK
-class QLocalSocket;
-#endif
+class QWifiSupplicant;
class QWifiEvent : public QEvent
{
@@ -91,13 +72,14 @@ public:
explicit QWifiController(QWifiManager *manager, QWifiManagerPrivate *managerPrivate);
~QWifiController();
- void call(Method method);
+ void asyncCall(Method method);
QWifiManager *wifiManager() const { return m_manager; }
bool isWifiThreadExitRequested() const { return m_exitEventThread; }
void startWifiEventThread();
void acquireIPAddress();
void stopDhcp() const;
bool resetSupplicantSocket();
+ QWifiSupplicant *supplicant() const { return m_supplicant; }
signals:
void backendStateChanged(QWifiManager::BackendState backendState);
@@ -108,25 +90,18 @@ protected:
void initializeBackend();
void terminateBackend();
void exitWifiEventThread();
- void allocateOnThisThread();
-#ifdef Q_OS_ANDROID_NO_SDK
- bool getQConnectivityReply();
-#else
void killDhcpProcess(const QString &path) const;
-#endif
private:
QWifiManager *m_manager;
QWifiManagerPrivate *const m_managerPrivate;
bool m_exitEventThread;
QByteArray m_interface;
-#ifdef Q_OS_ANDROID_NO_SDK
- QLocalSocket *m_qcSocket;
-#endif
QVector<Method> m_methods;
QWifiEventThread *m_eventThread;
QMutex m_methodsMutex;
QWaitCondition methodCallRequested;
+ QWifiSupplicant *m_supplicant;
};
QT_END_NAMESPACE
diff --git a/src/wifi/qwifidevice.cpp b/src/wifi/qwifidevice.cpp
index 0b52780..a6812e7 100644
--- a/src/wifi/qwifidevice.cpp
+++ b/src/wifi/qwifidevice.cpp
@@ -18,48 +18,12 @@
****************************************************************************/
#include "qwifidevice.h"
+#include <QtCore/QString>
#include <QtCore/QByteArray>
#include <QtCore/QDir>
-#ifdef Q_OS_ANDROID_NO_SDK
-#include <hardware_legacy/wifi.h>
-#include <cutils/properties.h>
-#endif
QT_BEGIN_NAMESPACE
-class QWifiDevicePrivate
-{
- Q_DECLARE_PUBLIC(QWifiDevice)
-public:
- QWifiDevicePrivate(QWifiDevice *device);
-
- // methods
- void createSupplicantConfig();
- // member variables
- QWifiDevice *const q_ptr;
-};
-
-QWifiDevicePrivate::QWifiDevicePrivate(QWifiDevice *device)
- : q_ptr(device)
-{
-}
-
-void QWifiDevicePrivate::createSupplicantConfig()
-{
- QFile supplicantConfig(QStringLiteral("/etc/wpa_supplicant.qtwifi.conf"));
- if (supplicantConfig.exists())
- return;
-
- if (supplicantConfig.open(QIODevice::WriteOnly)) {
- supplicantConfig.write("ctrl_interface=/var/run/wpa_supplicant\n"
- "ctrl_interface_group=0\n"
- "update_config=1\n");
- } else {
- qCWarning(B2QT_WIFI) << "failed to create supplicant configuration file.";
- }
-}
-
-
/*!
\class QWifiDevice
\inmodule B2Qt.Wifi.Cpp
@@ -82,9 +46,7 @@ void QWifiDevicePrivate::createSupplicantConfig()
*/
QWifiDevice::QWifiDevice()
- : d_ptr(new QWifiDevicePrivate(this))
{
- d_ptr->createSupplicantConfig();
}
QWifiDevice::~QWifiDevice()
@@ -97,41 +59,18 @@ QWifiDevice::~QWifiDevice()
*/
bool QWifiDevice::wifiSupported()
{
-#ifdef Q_OS_ANDROID_NO_SDK
- const char *fwpath = 0;
- // reload wifi firmware
- fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_STA);
- if (!fwpath) {
- qCWarning(B2QT_WIFI) << "failed to get firmware path";
- return false;
- }
- if (wifi_change_fw_path((const char *)fwpath)) {
- qCWarning(B2QT_WIFI) << "failed to change firmware path";
- return false;
- }
-#endif
QByteArray ifc = wifiInterfaceName();
bool hasInterface = QDir().exists(QString::fromLatin1("/sys/class/net/" + ifc));
if (!hasInterface)
qCWarning(B2QT_WIFI) << "could not find wifi interface in \"/sys/class/net/\", "
"looking for interface named: " << ifc;
-#ifdef Q_OS_ANDROID_NO_SDK
- if (hasInterface && wifi_load_driver() == 0) {
- return true;
- } else {
- qCWarning(B2QT_WIFI) << "wifi driver is not available";
- return false;
- }
-#else
return hasInterface;
-#endif
}
/*!
Returns Wifi interface name.
- \note On Android, the Wifi interface name is read from "wifi.interface"
- system property. On Linux, it is read from the \c B2QT_WIFI_INTERFACE
+ Interface name is read from the \c B2QT_WIFI_INTERFACE
environment variable if it is set, otherwise, the default interface
name ("\e{wlan0}") is used.
@@ -139,16 +78,7 @@ bool QWifiDevice::wifiSupported()
*/
QByteArray QWifiDevice::wifiInterfaceName()
{
- QByteArray ifc;
-#ifdef Q_OS_ANDROID_NO_SDK
- char interface[PROPERTY_VALUE_MAX];
- property_get("wifi.interface", interface, NULL);
- ifc = interface[0] == '\0' ? "wlan0" : interface;
-#else
- ifc = qEnvironmentVariableIsSet("B2QT_WIFI_INTERFACE")
- ? qgetenv("B2QT_WIFI_INTERFACE") : "wlan0";
-#endif
- return ifc;
+ return qEnvironmentVariableIsSet("B2QT_WIFI_INTERFACE") ? qgetenv("B2QT_WIFI_INTERFACE") : "wlan0";
}
/*!
@@ -158,11 +88,7 @@ QByteArray QWifiDevice::wifiInterfaceName()
*/
void QWifiDevice::setWifiInterfaceName(const QByteArray &name)
{
-#ifdef Q_OS_ANDROID_NO_SDK
- property_set("wifi.interface", name);
-#else
qputenv("B2QT_WIFI_INTERFACE", name);
-#endif
}
QT_END_NAMESPACE
diff --git a/src/wifi/qwifidevice.h b/src/wifi/qwifidevice.h
index 02724b4..80b4891 100644
--- a/src/wifi/qwifidevice.h
+++ b/src/wifi/qwifidevice.h
@@ -23,8 +23,6 @@
#include <QtCore/QByteArray>
#include <QtCore/QLoggingCategory>
-class QWifiDevicePrivate;
-
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(B2QT_WIFI)
@@ -39,11 +37,6 @@ public:
Q_INVOKABLE static bool wifiSupported();
static QByteArray wifiInterfaceName();
static void setWifiInterfaceName(const QByteArray &name);
-
-private:
- Q_DISABLE_COPY(QWifiDevice)
- Q_DECLARE_PRIVATE(QWifiDevice)
- QWifiDevicePrivate *const d_ptr;
};
QT_END_NAMESPACE
diff --git a/src/wifi/qwifielinux.cpp b/src/wifi/qwifielinux.cpp
deleted file mode 100644
index 1f3c67a..0000000
--- a/src/wifi/qwifielinux.cpp
+++ /dev/null
@@ -1,337 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include "qwifielinux_p.h"
-#include "qwifidevice.h"
-
-#include <QtCore/QFile>
-#include <QtCore/QProcess>
-
-#include "wpa-supplicant/wpa_ctrl.h"
-
-#include <poll.h>
-#include <unistd.h>
-#include <sys/socket.h>
-
-QT_BEGIN_NAMESPACE
-
-// TODO: When cleaning up the library from Android code move this into a proper class
-// (QWifiDevice?) since we won't depend on C style API from Android anymore.
-
-const char SUPP_CONFIG_FILE[] = "/etc/wpa_supplicant.qtwifi.conf";
-const char IFACE_DIR[] = "/var/run/wpa_supplicant/";
-const char WPA_EVENT_IGNORE[] = "CTRL-EVENT-IGNORE ";
-
-static struct wpa_ctrl *ctrl_conn;
-static struct wpa_ctrl *monitor_conn;
-// socket pair used to exit from a blocking read
-static int exit_sockets[2];
-
-int wifi_connect_on_socket_path(const char *path);
-int wifi_ctrl_recv(char *reply, size_t *reply_len);
-int wifi_wait_on_socket(char *buf, size_t buflen);
-int wifi_send_command(const char *cmd, char *reply, size_t *reply_len);
-void wifi_close_sockets();
-
-QByteArray controlInterfacePath()
-{
- QByteArray path;
- QFile configFile;
- configFile.setFileName(QLatin1String(SUPP_CONFIG_FILE));
- if (configFile.open(QFile::ReadOnly)) {
- while (!configFile.atEnd()) {
- QByteArray line = configFile.readLine().trimmed();
- if (line.startsWith("ctrl_interface")) {
- path = line.mid(15);
- if (path.isEmpty())
- qCWarning(B2QT_WIFI) << "ctrl_interface is not set in " << SUPP_CONFIG_FILE;
- break;
- }
- }
- configFile.close();
- } else {
- qCWarning(B2QT_WIFI) << "could not find/read wpa_supplicant configuration file in" << SUPP_CONFIG_FILE;
- }
- return path;
-}
-
-int q_wifi_start_supplicant()
-{
- QByteArray ifc = QWifiDevice::wifiInterfaceName();
- QString pidFile = QLatin1String("/var/run/wpa_supplicant." + ifc + ".pid");
- QString driver(QStringLiteral("nl80211,wext"));
-
- QStringList arg;
- arg << QStringLiteral("--start") << QStringLiteral("--quiet") << QStringLiteral("--name");
- arg << QStringLiteral("wpa_supplicant") << QStringLiteral("--startas");
- arg << QStringLiteral("/usr/sbin/wpa_supplicant") << QStringLiteral("--pidfile") << pidFile;
- arg << QStringLiteral("--") << QStringLiteral("-B") << QStringLiteral("-P") << pidFile;
- arg << QStringLiteral("-i") << QLatin1String(ifc) << QStringLiteral("-c");
- arg << QLatin1String(SUPP_CONFIG_FILE) << QStringLiteral("-D") << driver;
-
- QProcess ssDaemon;
- ssDaemon.start(QStringLiteral("start-stop-daemon"), arg);
- ssDaemon.waitForFinished();
- qCDebug(B2QT_WIFI) << ssDaemon.readAll();
-
- QByteArray path = controlInterfacePath();
- if (path.isEmpty())
- return -1;
-
- // if the interface socket exists then wpa-supplicant was invoked successfully
- if (!QFile(QLatin1String(path + "/" + ifc)).exists()) {
- qCWarning(B2QT_WIFI) << "failed to invoke wpa_supplicant!\n" << ssDaemon.readAll();
- return -1;
- }
- // reset sockets used for exiting from hung state
- exit_sockets[0] = exit_sockets[1] = -1;
- return 0;
-}
-
-int q_wifi_stop_supplicant()
-{
- QByteArray ifc = QWifiDevice::wifiInterfaceName();
- QString pidFile = QLatin1String("/var/run/wpa_supplicant." + ifc + ".pid");
-
- if (QFile(pidFile).exists()) {
- QStringList arg;
- arg << QStringLiteral("--stop") << QStringLiteral("--quiet") << QStringLiteral("--name");
- arg << QStringLiteral("wpa_supplicant") << QStringLiteral("--pidfile") << pidFile;
-
- QProcess ssDaemon;
- ssDaemon.start(QStringLiteral("start-stop-daemon"), arg);
- ssDaemon.waitForFinished();
- if (ssDaemon.exitStatus() != QProcess::NormalExit) {
- qCWarning(B2QT_WIFI) << "failed to stop a supplicant process!\n" << ssDaemon.readAll();;
- return -1;
- }
-
- QFile::remove(pidFile);
- }
-
- QByteArray path = controlInterfacePath();
- if (path.isEmpty())
- return -1;
-
- QFile::remove(QLatin1String(path + "/" + ifc));
-
- // workaround for QTEE-957
- QProcess killall;
- killall.start(QStringLiteral("killall"), QStringList() << QStringLiteral("-9") << QStringLiteral("wpa_supplicant"));
- killall.waitForFinished();
-
- return 0;
-}
-
-int q_wifi_connect_to_supplicant(const char *ifname)
-{
- static char path[4096];
- snprintf(path, sizeof(path), "%s/%s", IFACE_DIR, ifname);
- return wifi_connect_on_socket_path(path);
-}
-
-int wifi_connect_on_socket_path(const char *path)
-{
- // establishes the control and monitor socket connections on the interface
- ctrl_conn = wpa_ctrl_open(path);
- if (ctrl_conn == NULL) {
- qCWarning(B2QT_WIFI, "Unable to open connection to supplicant on \"%s\": %s",
- path, strerror(errno));
- return -1;
- }
- monitor_conn = wpa_ctrl_open(path);
- if (monitor_conn == NULL) {
- wpa_ctrl_close(ctrl_conn);
- ctrl_conn = NULL;
- return -1;
- }
- if (wpa_ctrl_attach(monitor_conn) != 0) {
- wpa_ctrl_close(monitor_conn);
- wpa_ctrl_close(ctrl_conn);
- ctrl_conn = monitor_conn = NULL;
- return -1;
- }
-
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, exit_sockets) == -1) {
- wpa_ctrl_close(monitor_conn);
- wpa_ctrl_close(ctrl_conn);
- ctrl_conn = monitor_conn = NULL;
- return -1;
- }
-
- return 0;
-}
-
-int q_wifi_wait_for_event(const char *ifname, char *buf, size_t buflen)
-{
- Q_UNUSED(ifname);
- return wifi_wait_on_socket(buf, buflen);
-}
-
-int wifi_wait_on_socket(char *buf, size_t buflen)
-{
- size_t nread = buflen - 1;
- int result;
- char *match, *match2;
-
- if (monitor_conn == NULL) {
- return snprintf(buf, buflen, WPA_EVENT_TERMINATING " - connection closed");
- }
-
- result = wifi_ctrl_recv(buf, &nread);
-
- /* Terminate reception on exit socket */
- if (result == -2) {
- return snprintf(buf, buflen, WPA_EVENT_TERMINATING " - connection closed");
- }
-
- if (result < 0) {
- qCWarning(B2QT_WIFI, "wifi_ctrl_recv failed: %s", strerror(errno));
- return snprintf(buf, buflen, WPA_EVENT_TERMINATING " - recv error");
- }
- buf[nread] = '\0';
- /* Check for EOF on the socket */
- if (result == 0 && nread == 0) {
- /* Fabricate an event to pass up */
- qCWarning(B2QT_WIFI, "Received EOF on supplicant socket");
- return snprintf(buf, buflen, WPA_EVENT_TERMINATING " - signal 0 received");
- }
- /*
- * Events strings are in the format
- *
- * IFNAME=iface <N>CTRL-EVENT-XXX
- * or
- * <N>CTRL-EVENT-XXX
- *
- * where N is the message level in numerical form (0=VERBOSE, 1=DEBUG,
- * etc.) and XXX is the event name. The level information is not useful
- * to us, so strip it off.
- */
-
- if (strncmp(buf, "IFNAME=", (sizeof("IFNAME=") - 1)) == 0) {
- match = strchr(buf, ' ');
- if (match != NULL) {
- if (match[1] == '<') {
- match2 = strchr(match + 2, '>');
- if (match2 != NULL) {
- nread -= (match2 - match);
- memmove(match + 1, match2 + 1, nread - (match - buf) + 1);
- }
- }
- } else {
- return snprintf(buf, buflen, "%s", WPA_EVENT_IGNORE);
- }
- } else if (buf[0] == '<') {
- match = strchr(buf, '>');
- if (match != NULL) {
- nread -= (match + 1 - buf);
- memmove(buf, match + 1, nread + 1);
- //qCWarning(B2QT_WIFI, "supplicant generated event without interface - %s", buf);
- }
- } else {
- /* let the event go as is! */
- qCWarning(B2QT_WIFI, "supplicant generated event without interface and without message level - %s", buf);
- }
-
- return nread;
-}
-
-int wifi_ctrl_recv(char *reply, size_t *reply_len)
-{
- int res = 0;
- int ctrlfd = wpa_ctrl_get_fd(monitor_conn);
- struct pollfd rfds[2];
-
- memset(rfds, 0, 2 * sizeof(struct pollfd));
- rfds[0].fd = ctrlfd;
- rfds[0].events |= POLLIN;
- rfds[1].fd = exit_sockets[1];
- rfds[1].events |= POLLIN;
- res = TEMP_FAILURE_RETRY(poll(rfds, 2, -1));
- if (res < 0) {
- qCWarning(B2QT_WIFI, "Error poll = %d", res);
- return res;
- }
- if (rfds[0].revents & POLLIN) {
- return wpa_ctrl_recv(monitor_conn, reply, reply_len);
- }
-
- /* it is not rfds[0], then it must be rfts[1] (i.e. the exit socket)
- * or we timed out. In either case, this call has failed ..
- */
- return -2;
-}
-
-int wifi_send_command(const char *cmd, char *reply, size_t *reply_len)
-{
- int ret;
- if (ctrl_conn == NULL) {
- qCWarning(B2QT_WIFI, "Not connected to wpa_supplicant - \"%s\" command dropped.", cmd);
- return -1;
- }
- ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), reply, reply_len, NULL);
- if (ret == -2) {
- qCWarning(B2QT_WIFI, "'%s' command timed out.", cmd);
- /* unblocks the monitor receive socket for termination */
- TEMP_FAILURE_RETRY(write(exit_sockets[0], "T", 1));
- return -2;
- } else if (ret < 0 || strncmp(reply, "FAIL", 4) == 0) {
- return -1;
- }
- if (strncmp(cmd, "PING", 4) == 0) {
- reply[*reply_len] = '\0';
- }
- return 0;
-}
-
-int q_wifi_command(const char *ifname, const char *command, char *reply, size_t *reply_len)
-{
- Q_UNUSED(ifname);
- return wifi_send_command(command, reply, reply_len);
-}
-
-void q_wifi_close_supplicant_connection(const char *ifname)
-{
- Q_UNUSED(ifname)
- wifi_close_sockets();
-}
-
-void wifi_close_sockets()
-{
- if (ctrl_conn != NULL) {
- wpa_ctrl_close(ctrl_conn);
- ctrl_conn = NULL;
- }
-
- if (monitor_conn != NULL) {
- wpa_ctrl_close(monitor_conn);
- monitor_conn = NULL;
- }
-
- if (exit_sockets[0] >= 0) {
- close(exit_sockets[0]);
- exit_sockets[0] = -1;
- }
-
- if (exit_sockets[1] >= 0) {
- close(exit_sockets[1]);
- exit_sockets[1] = -1;
- }
-}
-
-QT_END_NAMESPACE
diff --git a/src/wifi/qwifielinux_p.h b/src/wifi/qwifielinux_p.h
deleted file mode 100644
index bef90c3..0000000
--- a/src/wifi/qwifielinux_p.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#ifndef LOCAL_WIFI_H
-#define LOCAL_WIFI_H
-
-#include <QtCore/QLoggingCategory>
-
-#include <string.h>
-
-QT_BEGIN_NAMESPACE
-
-Q_DECLARE_LOGGING_CATEGORY(B2QT_WIFI)
-
-// This API mirrors Android's Wi-Fi libraries interface [1] and parts of implementation.
-// [1] http://androidxref.com/4.4.2_r2/xref/hardware/libhardware_legacy/include/hardware_legacy/wifi.h
-
-int q_wifi_command(const char *ifname, const char *command, char *reply, size_t *reply_len);
-int q_wifi_wait_for_event(const char *ifname, char *buf, size_t buflen);
-int q_wifi_connect_to_supplicant(const char *ifname);
-void q_wifi_close_supplicant_connection(const char *ifname);
-int q_wifi_start_supplicant();
-int q_wifi_stop_supplicant();
-
-QT_END_NAMESPACE
-
-#endif // LOCAL_WIFI_H
diff --git a/src/wifi/qwifimanager.cpp b/src/wifi/qwifimanager.cpp
index 739b399..6bace8f 100644
--- a/src/wifi/qwifimanager.cpp
+++ b/src/wifi/qwifimanager.cpp
@@ -20,7 +20,7 @@
#include "qwifinetworklistmodel_p.h"
#include "qwifinetwork_p.h"
#include "qwifimanager_p.h"
-#include "qwifiutils_p.h"
+#include "qwifisupplicant_p.h"
#include "qwifidevice.h"
@@ -36,8 +36,7 @@ const char *bsText[] = { "Initializing", "Running", "Terminating", "NotRunning"
QWifiManagerPrivate::QWifiManagerPrivate(QWifiManager *manager)
: q_ptr(manager)
- , m_networkListModel(new QWifiNetworkListModel())
- , m_device(new QWifiDevice())
+ , m_networkListModel(new QWifiNetworkListModel(manager))
, m_scanTimer(0)
, m_scanning(false)
, m_interface(QWifiDevice::wifiInterfaceName())
@@ -50,8 +49,6 @@ QWifiManagerPrivate::QWifiManagerPrivate(QWifiManager *manager)
QWifiManagerPrivate::~QWifiManagerPrivate()
{
delete m_wifiController;
- delete m_networkListModel;
- delete m_device;
}
void QWifiManagerPrivate::setCurrentSSID(const QString &ssid)
@@ -71,7 +68,7 @@ void QWifiManagerPrivate::handleAuthenticating(QWifiEvent *event)
QString ssid = data.mid(data.indexOf(QLatin1String("SSID")) + 6);
ssid = ssid.left(ssid.lastIndexOf(QLatin1Char('\'')));
- setCurrentSSID(QWifiUtils::decodeHexEncoded(ssid));
+ setCurrentSSID(QWifiSupplicant::decodeHexEncoded(ssid));
updateNetworkState(QWifiManager::Authenticating);
}
@@ -79,7 +76,7 @@ void QWifiManagerPrivate::handleConnected()
{
qCDebug(B2QT_WIFI) << "connected network: " << m_currentSSID;
updateNetworkState(QWifiManager::ObtainingIPAddress);
- m_wifiController->call(QWifiController::AcquireIPAddress);
+ m_wifiController->asyncCall(QWifiController::AcquireIPAddress);
}
void QWifiManagerPrivate::handleDisconneced()
@@ -111,20 +108,10 @@ void QWifiManagerPrivate::updateBackendState(QWifiManager::BackendState backendS
void QWifiManagerPrivate::updateWifiState()
{
- bool supplicantRunning = false;
-#ifdef Q_OS_ANDROID_NO_SDK
- char supplicantState[PROPERTY_VALUE_MAX];
- if (property_get("init.svc.wpa_supplicant", supplicantState, 0)) {
- if (strcmp(supplicantState, "running") == 0)
- supplicantRunning = true;
- }
-#else
QProcess ps;
ps.start(QStringLiteral("ps"));
ps.waitForFinished();
- if (ps.readAll().contains("wpa_supplicant"))
- supplicantRunning = true;
-#endif
+ bool supplicantRunning = ps.readAll().contains("wpa_supplicant");
if (supplicantRunning && m_wifiController->resetSupplicantSocket())
m_backendState = QWifiManager::Running;
}
@@ -134,25 +121,14 @@ QString QWifiManagerPrivate::call(const QString &command)
if (m_backendState != QWifiManager::Running)
return QString();
- char data[2048];
- size_t len = sizeof(data) - 1; // -1: room to add a 0-terminator
- QString actualCommand = command;
-#ifdef Q_OS_ANDROID_NO_SDK
-#if !(Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR < 4)
- QString prefix = QLatin1String("IFNAME=" + m_interface + " ");
- actualCommand.prepend(prefix);
-#endif
-#endif
- qCDebug(B2QT_WIFI) << "call command: " << actualCommand.toLocal8Bit();
- if (q_wifi_command(m_interface, actualCommand.toLocal8Bit(), data, &len) < 0) {
+ QByteArray reply;
+ bool success = m_wifiController->supplicant()->sendCommand(command, &reply);
+ if (!success) {
qCDebug(B2QT_WIFI) << "call to supplicant failed!";
return QString();
}
- if (len < sizeof(data))
- data[len] = 0;
- QString result = QLatin1String(data);
- return result.trimmed();
+ return QLatin1String(reply.trimmed());
}
bool QWifiManagerPrivate::checkedCall(const QString &command)
@@ -258,7 +234,7 @@ QWifiManager::QWifiManager()
QWifiManager::~QWifiManager()
{
Q_D(QWifiManager);
- d->m_wifiController->call(QWifiController::ExitEventLoop);
+ d->m_wifiController->asyncCall(QWifiController::ExitEventLoop);
d->m_wifiController->wait();
delete d_ptr;
}
@@ -326,7 +302,7 @@ QWifiManager::BackendState QWifiManager::backendState() const
void QWifiManager::start()
{
Q_D(QWifiManager);
- d->m_wifiController->call(QWifiController::InitializeBackend);
+ d->m_wifiController->asyncCall(QWifiController::InitializeBackend);
}
/*!
@@ -339,7 +315,7 @@ void QWifiManager::start()
void QWifiManager::stop()
{
Q_D(QWifiManager);
- d->m_wifiController->call(QWifiController::TerminateBackend);
+ d->m_wifiController->asyncCall(QWifiController::TerminateBackend);
}
/*!
@@ -371,7 +347,7 @@ void QWifiManager::setScanning(bool scanning)
emit scanningChanged(d->m_scanning);
if (d->m_scanning) {
d->call(QStringLiteral("SCAN"));
- // ### TODO android has property for this - wifi.supplicant_scan_interval
+ // ### TODO expose this with a property
d->m_scanTimer = startTimer(5000);
} else {
killTimer(d->m_scanTimer);
@@ -449,7 +425,7 @@ bool QWifiManager::connect(QWifiConfiguration *config)
const QStringList configuredNetworks = d->call(QStringLiteral("LIST_NETWORKS")).split('\n');
for (int i = 1; i < configuredNetworks.length(); ++i) {
const QStringList networkFields = configuredNetworks.at(i).split('\t');
- const QString ssid = QWifiUtils::decodeHexEncoded(networkFields.at(1));
+ const QString ssid = QWifiSupplicant::decodeHexEncoded(networkFields.at(1));
if (ssid == d->m_currentSSID) {
id = networkFields.at(0);
networkKnown = true;
@@ -483,7 +459,7 @@ bool QWifiManager::connect(QWifiConfiguration *config)
// ref: https://www.freebsd.org/cgi/man.cgi?wpa_supplicant.conf
// ----------------------------------------------------------------------
if (protocol.isEmpty() || protocol.contains(QStringLiteral("WPA"))) {
- // ### todo - password length has limits (see IEEE 802.11), we need to check
+ // ### TODO - password length has limits (see IEEE 802.11), we need to check
// for those limits here. Supplicant gives only a meaningless "fail" message.
ok = ok && d->checkedCall(setNetworkCommand + QLatin1String(" psk ") + q + psk + q);
key_mgmt = QLatin1String("WPA-PSK");
@@ -522,7 +498,7 @@ void QWifiManager::disconnect()
{
Q_D(QWifiManager);
d->call(QStringLiteral("DISCONNECT"));
- d->m_wifiController->call(QWifiController::StopDhcp);
+ d->m_wifiController->asyncCall(QWifiController::StopDhcp);
}
void QWifiManager::handleBackendStateChanged(BackendState backendState)
diff --git a/src/wifi/qwifimanager_p.h b/src/wifi/qwifimanager_p.h
index 1046880..5449551 100644
--- a/src/wifi/qwifimanager_p.h
+++ b/src/wifi/qwifimanager_p.h
@@ -53,7 +53,6 @@ public:
QWifiManager *const q_ptr;
QWifiController *m_wifiController;
QWifiNetworkListModel *m_networkListModel;
- QWifiDevice *m_device;
int m_scanTimer;
bool m_scanning;
diff --git a/src/wifi/qwifinetworklistmodel.cpp b/src/wifi/qwifinetworklistmodel.cpp
index 9d6202f..a1f825f 100644
--- a/src/wifi/qwifinetworklistmodel.cpp
+++ b/src/wifi/qwifinetworklistmodel.cpp
@@ -18,7 +18,7 @@
****************************************************************************/
#include "qwifinetworklistmodel_p.h"
#include "qwifinetwork_p.h"
-#include "qwifiutils_p.h"
+#include "qwifisupplicant_p.h"
#include "qwifimanager.h"
@@ -124,7 +124,7 @@ void QWifiNetworkListModel::parseScanResults(const QString &results)
continue;
int pos = 0;
- QString ssid = QWifiUtils::decodeHexEncoded(info.at(4));
+ QString ssid = QWifiSupplicant::decodeHexEncoded(info.at(4));
if (ssid.isEmpty())
continue;
diff --git a/src/wifi/qwifisupplicant.cpp b/src/wifi/qwifisupplicant.cpp
new file mode 100644
index 0000000..7b303ed
--- /dev/null
+++ b/src/wifi/qwifisupplicant.cpp
@@ -0,0 +1,420 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use the contact form at
+** http://www.qt.io
+**
+** This file is part of Qt Enterprise Embedded.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** the contact form at http://www.qt.io
+**
+****************************************************************************/
+#include "qwifisupplicant_p.h"
+#include "qwifidevice.h"
+
+#include <poll.h>
+#include <unistd.h>
+#include <sys/socket.h>
+
+#include <QtCore/QFile>
+#include <QtCore/QProcess>
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(B2QT_WIFI_VERBOSE, "qt.b2qt.wifi.verbose")
+
+#define CONFIG_FILE "/etc/wpa_supplicant.qtwifi.conf"
+#define CONTROL_INTERFACE_PATH "/var/run/wpa_supplicant/"
+
+QWifiSupplicant::QWifiSupplicant(QObject *parent) :
+ QObject(parent),
+ ctrl_conn(0),
+ monitor_conn(0),
+ interface(QWifiDevice::wifiInterfaceName())
+{
+ createSupplicantConfig();
+}
+
+void QWifiSupplicant::createSupplicantConfig() const
+{
+ QFile supplicantConfig(QLatin1String(CONFIG_FILE));
+ if (supplicantConfig.exists())
+ return;
+
+ if (supplicantConfig.open(QIODevice::WriteOnly)) {
+ supplicantConfig.write("ctrl_interface=" CONTROL_INTERFACE_PATH "\n"
+ "ctrl_interface_group=0\n"
+ "update_config=1\n");
+ } else {
+ qCWarning(B2QT_WIFI) << "failed to create supplicant configuration file.";
+ }
+}
+
+bool QWifiSupplicant::startSupplicant()
+{
+ QString pidFile = QLatin1String("/var/run/wpa_supplicant." + interface + ".pid");
+ QString driver(QStringLiteral("nl80211,wext"));
+
+ QStringList arg;
+ arg << QStringLiteral("--start") << QStringLiteral("--quiet") << QStringLiteral("--name");
+ arg << QStringLiteral("wpa_supplicant") << QStringLiteral("--startas");
+ arg << QStringLiteral("/usr/sbin/wpa_supplicant") << QStringLiteral("--pidfile") << pidFile;
+ arg << QStringLiteral("--") << QStringLiteral("-B") << QStringLiteral("-P") << pidFile;
+ arg << QStringLiteral("-i") << QLatin1String(interface) << QStringLiteral("-c");
+ arg << QLatin1String(CONFIG_FILE) << QStringLiteral("-D") << driver;
+
+ QProcess startStopDaemon;
+ startStopDaemon.start(QStringLiteral("start-stop-daemon"), arg);
+ startStopDaemon.waitForFinished();
+ qCDebug(B2QT_WIFI) << startStopDaemon.readAll();
+
+ // if the interface socket exists then wpa-supplicant was invoked successfully
+ if (!QFile(QLatin1String(CONTROL_INTERFACE_PATH + interface)).exists()) {
+ qCWarning(B2QT_WIFI) << "failed to invoke wpa_supplicant!\n" << startStopDaemon.readAll();
+ return false;
+ }
+ // reset sockets used for exiting from hung state
+ exit_sockets[0] = exit_sockets[1] = -1;
+ return true;
+}
+
+bool QWifiSupplicant::stopSupplicant()
+{
+ QString pidFile = QLatin1String("/var/run/wpa_supplicant." + interface + ".pid");
+
+ if (QFile(pidFile).exists()) {
+ QStringList arg;
+ arg << QStringLiteral("--stop") << QStringLiteral("--quiet") << QStringLiteral("--name");
+ arg << QStringLiteral("wpa_supplicant") << QStringLiteral("--pidfile") << pidFile;
+
+ QProcess startStopDaemon;
+ startStopDaemon.start(QStringLiteral("start-stop-daemon"), arg);
+ startStopDaemon.waitForFinished();
+ if (startStopDaemon.exitStatus() != QProcess::NormalExit) {
+ qCWarning(B2QT_WIFI) << "failed to stop a supplicant process!\n" << startStopDaemon.readAll();
+ return false;
+ }
+
+ QFile::remove(pidFile);
+ }
+
+ QFile::remove(QLatin1String(CONTROL_INTERFACE_PATH + interface));
+
+ // workaround for QTEE-957
+ QProcess killall;
+ killall.start(QStringLiteral("killall"), QStringList() << QStringLiteral("-9") << QStringLiteral("wpa_supplicant"));
+ killall.waitForFinished();
+
+ return true;
+}
+
+bool QWifiSupplicant::connectToSupplicant()
+{
+ static char path[4096];
+ snprintf(path, sizeof(path), "%s/%s", CONTROL_INTERFACE_PATH, interface.constData());
+
+ ctrl_conn = wpa_ctrl_open(path);
+ if (ctrl_conn == NULL) {
+ qCWarning(B2QT_WIFI, "Unable to open connection to supplicant on \"%s\": %s",
+ path, strerror(errno));
+ return false;
+ }
+ monitor_conn = wpa_ctrl_open(path);
+ if (monitor_conn == NULL) {
+ wpa_ctrl_close(ctrl_conn);
+ ctrl_conn = NULL;
+ return false;
+ }
+ if (wpa_ctrl_attach(monitor_conn) != 0) {
+ wpa_ctrl_close(monitor_conn);
+ wpa_ctrl_close(ctrl_conn);
+ ctrl_conn = monitor_conn = NULL;
+ return false;
+ }
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, exit_sockets) == -1) {
+ wpa_ctrl_close(monitor_conn);
+ wpa_ctrl_close(ctrl_conn);
+ ctrl_conn = monitor_conn = NULL;
+ return false;
+ }
+
+ return true;
+}
+
+void QWifiSupplicant::closeSupplicantConnection()
+{
+ if (ctrl_conn != NULL) {
+ wpa_ctrl_close(ctrl_conn);
+ ctrl_conn = NULL;
+ }
+
+ if (monitor_conn != NULL) {
+ wpa_ctrl_close(monitor_conn);
+ monitor_conn = NULL;
+ }
+
+ if (exit_sockets[0] >= 0) {
+ close(exit_sockets[0]);
+ exit_sockets[0] = -1;
+ }
+
+ if (exit_sockets[1] >= 0) {
+ close(exit_sockets[1]);
+ exit_sockets[1] = -1;
+ }
+}
+
+int QWifiSupplicant::waitForEvent(char *buf, size_t buflen)
+{
+ size_t nread = buflen - 1;
+ int result;
+ char *match, *match2;
+
+ if (monitor_conn == NULL)
+ return snprintf(buf, buflen, WPA_EVENT_TERMINATING " - connection closed");
+
+ result = receiveEvent(buf, &nread);
+
+ // Terminate reception on exit socket
+ if (result == -2)
+ return snprintf(buf, buflen, WPA_EVENT_TERMINATING " - connection closed");
+
+ if (result < 0) {
+ qCWarning(B2QT_WIFI, "receiveEvent failed: %s", strerror(errno));
+ return snprintf(buf, buflen, WPA_EVENT_TERMINATING " - recv error");
+ }
+
+ buf[nread] = '\0';
+ // Check for EOF on the socket
+ if (result == 0 && nread == 0) {
+ // Fabricate an event to pass up
+ qCWarning(B2QT_WIFI, "Received EOF on supplicant socket");
+ return snprintf(buf, buflen, WPA_EVENT_TERMINATING " - signal 0 received");
+ }
+
+ /*
+ * Events strings are in the format
+ *
+ * IFNAME=iface <N>CTRL-EVENT-XXX
+ * or
+ * <N>CTRL-EVENT-XXX
+ *
+ * where N is the message level in numerical form (0=VERBOSE, 1=DEBUG,
+ * etc.) and XXX is the event name. The level information is not useful
+ * to us, so strip it off.
+ */
+
+ if (strncmp(buf, "IFNAME=", (sizeof("IFNAME=") - 1)) == 0) {
+ match = strchr(buf, ' ');
+ if (match != NULL) {
+ if (match[1] == '<') {
+ match2 = strchr(match + 2, '>');
+ if (match2 != NULL) {
+ nread -= (match2 - match);
+ memmove(match + 1, match2 + 1, nread - (match - buf) + 1);
+ }
+ }
+ } else {
+ return snprintf(buf, buflen, "%s", "CTRL-EVENT-IGNORE ");
+ }
+ } else if (buf[0] == '<') {
+ match = strchr(buf, '>');
+ if (match != NULL) {
+ nread -= (match + 1 - buf);
+ memmove(buf, match + 1, nread + 1);
+ //qCWarning(B2QT_WIFI, "supplicant generated event without interface - %s", buf);
+ }
+ } else {
+ // let the event go as is!
+ qCWarning(B2QT_WIFI, "supplicant generated event without interface and without message level - %s", buf);
+ }
+
+ return nread;
+}
+
+bool QWifiSupplicant::sendCommand(const QString &command, QByteArray *reply)
+{
+ QByteArray cmd = command.toLocal8Bit();
+ qCDebug(B2QT_WIFI) << "[command]: " << cmd;
+
+ if (ctrl_conn == NULL) {
+ qCWarning(B2QT_WIFI, "Not connected to wpa_supplicant");
+ return false;
+ }
+
+ char data[8192];
+ size_t len = sizeof(data) - 1; // -1: room to add a 0-terminator
+ int ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), data, &len, NULL);
+ if (ret == -2) {
+ qCWarning(B2QT_WIFI) << "command timed out";
+ // unblocks the monitor receive socket for termination
+ TEMP_FAILURE_RETRY(write(exit_sockets[0], "T", 1));
+ return false;
+ } else if (ret < 0 || strncmp(data, "FAIL", 4) == 0) {
+ return false;
+ }
+
+ if (len == sizeof(data) - 1) {
+ qCWarning(B2QT_WIFI) << "possible buffer overflow detected!";
+ return false;
+ }
+
+ data[len] = 0;
+ qCDebug(B2QT_WIFI_VERBOSE) << "[response]: " << data;
+ *reply = QByteArray(data, len);
+
+ return true;
+}
+
+int QWifiSupplicant::receiveEvent(char *reply, size_t *reply_len)
+{
+ int res = 0;
+ int ctrlfd = wpa_ctrl_get_fd(monitor_conn);
+ struct pollfd rfds[2];
+
+ memset(rfds, 0, 2 * sizeof(struct pollfd));
+ rfds[0].fd = ctrlfd;
+ rfds[0].events |= POLLIN;
+ rfds[1].fd = exit_sockets[1];
+ rfds[1].events |= POLLIN;
+ res = TEMP_FAILURE_RETRY(poll(rfds, 2, -1));
+ if (res < 0) {
+ qCWarning(B2QT_WIFI, "Error poll = %d", res);
+ return res;
+ }
+ if (rfds[0].revents & POLLIN) {
+ return wpa_ctrl_recv(monitor_conn, reply, reply_len);
+ }
+
+ /* it is not rfds[0], then it must be rfts[1] (i.e. the exit socket)
+ * or we timed out. In either case, this call has failed ..
+ */
+ return -2;
+}
+
+/*! \internal
+ *
+ Decode wpa_supplicant encoded string, see file hostapd/src/utils/common.c
+ in git://w1.fi/hostap.git repository.
+
+ For Ascii encoded string, any octet < 32 or > 127 is encoded as a "\\x"
+ followed by the hex representation of the octet. Exception chars are ",
+ \\, \\e, \\n, \\r, \\t which are escaped by a backslash
+
+ */
+QString QWifiSupplicant::decodeHexEncoded(const QString &encoded)
+{
+ int maxlen = encoded.size() + 1;
+ QByteArray buf;
+ buf.resize(maxlen);
+ const char *pos = encoded.toLocal8Bit().constData();
+ int len = 0;
+ int val;
+
+ while (*pos) {
+ if (len + 1 >= maxlen)
+ break;
+ switch (*pos) {
+ case '\\':
+ pos++;
+ switch (*pos) {
+ case '\\':
+ buf[len++] = '\\';
+ pos++;
+ break;
+ case '"':
+ buf[len++] = '"';
+ pos++;
+ break;
+ case 'n':
+ buf[len++] = '\n';
+ pos++;
+ break;
+ case 'r':
+ buf[len++] = '\r';
+ pos++;
+ break;
+ case 't':
+ buf[len++] = '\t';
+ pos++;
+ break;
+ case 'e':
+ buf[len++] = '\033';
+ pos++;
+ break;
+ case 'x':
+ pos++;
+ val = hex2byte(pos);
+ if (val < 0) {
+ val = hex2num(*pos);
+ if (val < 0)
+ break;
+ buf[len++] = val;
+ pos++;
+ } else {
+ buf[len++] = val;
+ pos += 2;
+ }
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ val = *pos++ - '0';
+ if (*pos >= '0' && *pos <= '7')
+ val = val * 8 + (*pos++ - '0');
+ if (*pos >= '0' && *pos <= '7')
+ val = val * 8 + (*pos++ - '0');
+ buf[len++] = val;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ buf[len++] = *pos++;
+ break;
+ }
+ }
+ if (maxlen > len)
+ buf[len] = '\0';
+
+ return QString::fromUtf8(buf);
+}
+
+int QWifiSupplicant::hex2num(char c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ return -1;
+}
+
+int QWifiSupplicant::hex2byte(const char *hex)
+{
+ int a, b;
+ a = hex2num(*hex++);
+ if (a < 0)
+ return -1;
+ b = hex2num(*hex++);
+ if (b < 0)
+ return -1;
+ return (a << 4) | b;
+}
+
+QT_END_NAMESPACE
diff --git a/src/wifi/qwifiutils_p.h b/src/wifi/qwifisupplicant_p.h
index 8b3e54a..5119f9c 100644
--- a/src/wifi/qwifiutils_p.h
+++ b/src/wifi/qwifisupplicant_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2015 Digia Plc
+** Copyright (C) 2014 Digia Plc
** All rights reserved.
** For any questions to Digia, please use the contact form at
** http://www.qt.io
@@ -16,22 +16,46 @@
** the contact form at http://www.qt.io
**
****************************************************************************/
-#ifndef QWIFIUTILS_H
-#define QWIFIUTILS_H
+#ifndef QWIFISUPPLICANT_H
+#define QWIFISUPPLICANT_H
-#include <QtCore/QString>
+#include <QObject>
+#include <QByteArray>
+
+#include "wpa-supplicant/wpa_ctrl.h"
QT_BEGIN_NAMESPACE
-class QWifiUtils
+Q_DECLARE_LOGGING_CATEGORY(B2QT_WIFI)
+Q_DECLARE_LOGGING_CATEGORY(B2QT_WIFI_VERBOSE)
+
+class QWifiSupplicant : public QObject
{
+ Q_OBJECT
public:
+ explicit QWifiSupplicant(QObject *parent = 0);
+
+ void createSupplicantConfig() const;
+ bool startSupplicant();
+ bool stopSupplicant();
+ bool connectToSupplicant();
+ void closeSupplicantConnection();
+ int waitForEvent(char *buf, size_t buflen);
+ bool sendCommand(const QString &command, QByteArray *reply);
+ static QString decodeHexEncoded(const QString &encoded);
+
+protected:
+ int receiveEvent(char *reply, size_t *reply_len);
static int hex2num(char c);
static int hex2byte(const char *hex);
- static QString decodeHexEncoded(const QString &encoded);
+private:
+ wpa_ctrl *ctrl_conn;
+ wpa_ctrl *monitor_conn;
+ int exit_sockets[2];
+ QByteArray interface;
};
QT_END_NAMESPACE
-#endif // QWIFIUTILS_H
+#endif // QWIFISUPPLICANT_H
diff --git a/src/wifi/qwifiutils.cpp b/src/wifi/qwifiutils.cpp
deleted file mode 100644
index 21c440b..0000000
--- a/src/wifi/qwifiutils.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include "qwifiutils_p.h"
-
-QT_BEGIN_NAMESPACE
-
-int QWifiUtils::hex2num(char c)
-{
- if (c >= '0' && c <= '9')
- return c - '0';
- if (c >= 'a' && c <= 'f')
- return c - 'a' + 10;
- if (c >= 'A' && c <= 'F')
- return c - 'A' + 10;
- return -1;
-}
-
-int QWifiUtils::hex2byte(const char *hex)
-{
- int a, b;
- a = hex2num(*hex++);
- if (a < 0)
- return -1;
- b = hex2num(*hex++);
- if (b < 0)
- return -1;
- return (a << 4) | b;
-}
-
-// the logic of this function is taken from wpa_supplicant source code (BSD
-// licensed code) see http://w1.fi/cgit file hostapd/src/utils/common.c
-// For Ascii encoded string, any octet < 32 or > 127 is encoded as a "\x"
-// followed by the hex representation of the octet. Exception chars are ",
-// \, \e, \n, \r, \t which are escaped by a backslash
-QString QWifiUtils::decodeHexEncoded(const QString &encoded)
-{
- int maxlen = encoded.size() + 1;
- QByteArray buf;
- buf.resize(maxlen);
- const char *pos = encoded.toLocal8Bit().constData();
- int len = 0;
- int val;
-
- while (*pos) {
- if (len + 1 >= maxlen)
- break;
- switch (*pos) {
- case '\\':
- pos++;
- switch (*pos) {
- case '\\':
- buf[len++] = '\\';
- pos++;
- break;
- case '"':
- buf[len++] = '"';
- pos++;
- break;
- case 'n':
- buf[len++] = '\n';
- pos++;
- break;
- case 'r':
- buf[len++] = '\r';
- pos++;
- break;
- case 't':
- buf[len++] = '\t';
- pos++;
- break;
- case 'e':
- buf[len++] = '\033';
- pos++;
- break;
- case 'x':
- pos++;
- val = hex2byte(pos);
- if (val < 0) {
- val = hex2num(*pos);
- if (val < 0)
- break;
- buf[len++] = val;
- pos++;
- } else {
- buf[len++] = val;
- pos += 2;
- }
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- val = *pos++ - '0';
- if (*pos >= '0' && *pos <= '7')
- val = val * 8 + (*pos++ - '0');
- if (*pos >= '0' && *pos <= '7')
- val = val * 8 + (*pos++ - '0');
- buf[len++] = val;
- break;
- default:
- break;
- }
- break;
- default:
- buf[len++] = *pos++;
- break;
- }
- }
- if (maxlen > len)
- buf[len] = '\0';
-
- return QString::fromUtf8(buf);
-}
-
-QT_END_NAMESPACE
diff --git a/src/wifi/wifi.pro b/src/wifi/wifi.pro
index f248774..faf15f2 100644
--- a/src/wifi/wifi.pro
+++ b/src/wifi/wifi.pro
@@ -17,7 +17,7 @@ HEADERS += \
$$PWD/qwificontroller_p.h \
$$PWD/qwifidevice.h \
$$PWD/qwificonfiguration.h \
- $$PWD/qwifiutils_p.h
+ $$PWD/qwifisupplicant_p.h
SOURCES += \
$$PWD/qwifimanager.cpp \
@@ -26,20 +26,11 @@ SOURCES += \
$$PWD/qwificontroller.cpp \
$$PWD/qwifidevice.cpp \
$$PWD/qwificonfiguration.cpp \
- $$PWD/qwifiutils.cpp
+ $$PWD/qwifisupplicant.cpp \
+ $$[QT_SYSROOT]/usr/include/wpa-supplicant/wpa_ctrl.c \
+ $$[QT_SYSROOT]/usr/include/wpa-supplicant/os_unix.c
-android: {
- LIBS += -lhardware_legacy -lcutils
-} else {
- DEFINES += \
- CONFIG_CTRL_IFACE \
- CONFIG_CTRL_IFACE_UNIX
+DEFINES += \
+ CONFIG_CTRL_IFACE \
+ CONFIG_CTRL_IFACE_UNIX
- HEADERS += \
- $$PWD/qwifielinux_p.h
-
- SOURCES += \
- $$PWD/qwifielinux.cpp \
- $$[QT_SYSROOT]/usr/include/wpa-supplicant/wpa_ctrl.c \
- $$[QT_SYSROOT]/usr/include/wpa-supplicant/os_unix.c
-}