Adding VoiceCall interface support to ofono-qt Bindings Signed-off-by: Arun Ravindran...
authorArun Ravindran <ext-arun.1.ravindran@nokia.com>
Mon, 21 Feb 2011 13:03:43 +0000 (15:03 +0200)
committerAlexander Kanavin <ak@ak-desktop.(none)>
Wed, 23 Feb 2011 21:55:27 +0000 (23:55 +0200)
lib/lib.pro
lib/ofonovoicecall.cpp [new file with mode: 0644]
lib/ofonovoicecall.h [new file with mode: 0644]
tests/test_ofonovoicecall.cpp [new file with mode: 0644]
tests/test_ofonovoicecall.pro [new file with mode: 0644]
tests/tests.pro

index ab8d75a..84f5b70 100644 (file)
@@ -28,6 +28,7 @@ PUBLIC_HEADERS += ofononetworkoperator.h
 PUBLIC_HEADERS += ofononetworkregistration.h
 PUBLIC_HEADERS += ofonosupplementaryservices.h
 PUBLIC_HEADERS += ofonovoicecallmanager.h
+PUBLIC_HEADERS += ofonovoicecall.h
 
 HEADERS += $$PUBLIC_HEADERS
 HEADERS += ofonointerface.h 
@@ -49,6 +50,8 @@ SOURCES += ofononetworkoperator.cpp
 SOURCES += ofononetworkregistration.cpp
 SOURCES += ofonosupplementaryservices.cpp
 SOURCES += ofonovoicecallmanager.cpp
+SOURCES += ofonovoicecall.cpp
+
 
 target.path = $$[QT_INSTALL_PREFIX]/lib
 headers.files = $$PUBLIC_HEADERS
diff --git a/lib/ofonovoicecall.cpp b/lib/ofonovoicecall.cpp
new file mode 100644 (file)
index 0000000..87b4663
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * This file is part of ofono-qt
+ *
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: Alexander Kanavin <alexander.kanavin@nokia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <QtDBus/QtDBus>
+#include <QtCore/QObject>
+#include <QtCore/QDebug>
+
+#include "ofonointerface.h"
+#include "ofonovoicecall.h"
+
+#define VOICECALL_TIMEOUT 30000
+
+OfonoVoiceCall::OfonoVoiceCall(const QString& callId, QObject *parent)
+    : QObject(parent)
+{
+    m_if = new OfonoInterface(callId, "org.ofono.VoiceCall", OfonoGetAllOnStartup, this);
+
+    connect(m_if, SIGNAL(propertyChanged(const QString&, const QVariant&)),
+            this, SLOT(propertyChanged(const QString&, const QVariant&)));
+
+    QDBusConnection::systemBus().connect("org.ofono",path(),m_if->ifname(),
+                                         "DisconnectReason", this,
+                                         SIGNAL(disconnectReason(const QString&)));
+
+}
+
+OfonoVoiceCall::OfonoVoiceCall(const OfonoVoiceCall& call)
+    : QObject(call.parent())
+{
+    m_if = new OfonoInterface(call.path(), "org.ofono.VoiceCall", OfonoGetAllOnStartup, this);
+
+    connect(m_if, SIGNAL(propertyChanged(const QString&, const QVariant&)),
+            this, SLOT(propertyChanged(const QString&, const QVariant&)));
+
+    QDBusConnection::systemBus().connect("org.ofono",path(),m_if->ifname(),
+                                         "DisconnectReason", this,
+                                         SIGNAL(disconnectReason(const QString&)));
+}
+
+bool OfonoVoiceCall::operator==(const OfonoVoiceCall &call)
+{
+    return path() == call.path();
+}
+
+OfonoVoiceCall::~OfonoVoiceCall()
+{
+}
+
+void OfonoVoiceCall::answer()
+{
+    QDBusMessage request;
+
+    request = QDBusMessage::createMethodCall("org.ofono",
+                                             path(), m_if->ifname(),
+                                             "Answer");
+
+    QDBusConnection::systemBus().callWithCallback(request, this,
+                                        SLOT(answerResp()),
+                                        SLOT(answerErr(const QDBusError&)),
+                                        VOICECALL_TIMEOUT);
+}
+
+void OfonoVoiceCall::hangup()
+{
+    QDBusMessage request;
+
+    request = QDBusMessage::createMethodCall("org.ofono",
+                                             path(), m_if->ifname(),
+                                             "Hangup");
+
+    QDBusConnection::systemBus().callWithCallback(request, this,
+                                        SLOT(hangupResp()),
+                                        SLOT(hangupErr(const QDBusError&)),
+                                        VOICECALL_TIMEOUT);
+}
+
+void OfonoVoiceCall::deflect(const QString &number)
+{
+    QDBusMessage request;
+
+    request = QDBusMessage::createMethodCall("org.ofono",
+                                             path(), m_if->ifname(),
+                                             "Deflect");
+    QList<QVariant>arg;
+    arg.append(QVariant(number));
+    request.setArguments(arg);
+
+    QDBusConnection::systemBus().callWithCallback(request, this,
+                                        SLOT(deflectResp()),
+                                        SLOT(deflectErr(const QDBusError&)),
+                                        VOICECALL_TIMEOUT);
+}
+
+void OfonoVoiceCall::answerResp()
+{
+    emit answerComplete(TRUE);
+}
+
+void OfonoVoiceCall::answerErr(const QDBusError &error)
+{
+    qDebug() << "request failed" << error;
+    m_if->setError(error.name(), error.message());
+    emit answerComplete(FALSE);
+}
+
+void OfonoVoiceCall::hangupResp()
+{
+    emit hangupComplete(TRUE);
+}
+
+void OfonoVoiceCall::hangupErr(const QDBusError &error)
+{
+    qDebug() << "request failed" << error;
+    m_if->setError(error.name(), error.message());
+    emit hangupComplete(FALSE);
+}
+
+void OfonoVoiceCall::deflectResp()
+{
+    emit deflectComplete(TRUE);
+}
+
+void OfonoVoiceCall::deflectErr(const QDBusError &error)
+{
+    qDebug() << "request failed" << error;
+    m_if->setError(error.name(), error.message());
+    emit deflectComplete(FALSE);
+}
+
+QString OfonoVoiceCall::incomingLine() const
+{
+    return m_if->properties()["IncomingLine"].value<QString>();
+}
+
+QString OfonoVoiceCall::lineIdentification() const
+{
+    return m_if->properties()["LineIdentification"].value<QString>();
+}
+
+QString OfonoVoiceCall::name() const
+{
+    return m_if->properties()["Name"].value<QString>();
+}
+
+QString OfonoVoiceCall::state() const
+{
+    return m_if->properties()["State"].value<QString>();
+}
+
+QString OfonoVoiceCall::startTime() const
+{
+    return m_if->properties()["StartTime"].value<QString>();
+}
+
+QString OfonoVoiceCall::information() const
+{
+    return m_if->properties()["Information"].value<QString>();
+}
+
+bool OfonoVoiceCall::multiparty() const
+{
+    return m_if->properties()["Multiparty"].value<bool>();
+}
+
+bool OfonoVoiceCall::emergency() const
+{
+    return m_if->properties()["Emergency"].value<bool>();
+}
+
+void OfonoVoiceCall::propertyChanged(const QString &property, const QVariant &value)
+{
+    if (property == "LineIdentification") {
+        emit lineIdentificationChanged(value.value<QString>());
+    } else if (property == "Name") {
+        emit nameChanged(value.value<QString>());
+    } else if (property == "State") {
+        emit stateChanged(value.value<QString>());
+    } else if (property == "Information") {
+        emit informationChanged(value.value<QString>());
+    } else if (property == "IncomingLine") {
+        emit incomingLineChanged(value.value<QString>());
+    } else if (property == "Multiparty") {
+        emit multipartyChanged(value.value<bool>());
+    } else if (property == "Emergency") {
+        emit emergencyChanged(value.value<bool>());
+    } else if (property == "StartTime") {
+        emit startTimeChanged(value.value<QString>());
+    } else if (property == "Icon") {
+            emit iconChanged(value.value<quint8>());
+    }
+}
+
+QString OfonoVoiceCall::path() const
+{
+    return m_if->path();
+}
+
+QString OfonoVoiceCall::errorName() const
+{
+    return m_if->errorName();
+}
+
+QString OfonoVoiceCall::errorMessage() const
+{
+    return m_if->errorMessage();
+}
diff --git a/lib/ofonovoicecall.h b/lib/ofonovoicecall.h
new file mode 100644 (file)
index 0000000..8650a02
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * This file is part of ofono-qt
+ *
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: Alexander Kanavin <alexander.kanavin@nokia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+#ifndef OFONOVOICECALL_H
+#define OFONOVOICECALL_H
+
+#include <QtCore/QObject>
+#include <QVariant>
+#include <QStringList>
+#include <QDBusError>
+
+#include "libofono-qt_global.h"
+
+class OfonoInterface;
+
+//! This class is used to access oFono voice call API
+/*!
+ * The API is documented in
+ * http://git.kernel.org/?p=network/ofono/ofono.git;a=blob;f=doc/voicecall-api.txt
+ */
+class OFONO_QT_EXPORT OfonoVoiceCall : public QObject
+{
+    Q_OBJECT
+public:
+    OfonoVoiceCall(const QString &callId, QObject *parent=0);
+    OfonoVoiceCall(const OfonoVoiceCall &op);
+    ~OfonoVoiceCall();
+
+    bool operator==(const OfonoVoiceCall &op);
+
+    //! Returns the D-Bus object path of the voice call object
+    QString path() const;
+
+    //! Get the D-Bus error name of the last operation.
+    /*!
+     * Returns the D-Bus error name of the last operation (setting a property
+     * or calling a method) if it has failed
+     */
+    QString errorName() const;
+
+    //! Get the D-Bus error message of the last operation.
+    /*!
+     * Returns the D-Bus error message of the last operation (setting a property
+     * or calling a method) if it has failed
+     */
+    QString errorMessage() const;
+
+    void answer();
+    void hangup();
+    void deflect(const QString &number);
+    QString lineIdentification() const;
+    QString incomingLine() const;
+    QString name() const;
+    QString state() const;
+    QString startTime() const;
+    QString information() const;
+    bool multiparty() const;
+    bool emergency() const;
+
+signals:
+    void answerComplete(bool status);
+    void hangupComplete(bool status);
+    void deflectComplete(bool status);
+    void lineIdentificationChanged(const QString &name);
+    void nameChanged(const QString &name);
+    void stateChanged(const QString &state);
+    void startTimeChanged(const QString &time);
+    void informationChanged(const QString &mcc);
+    void incomingLineChanged(const QString &line);
+    void disconnectReason(const QString &reason);
+    void multipartyChanged(const bool multiparty);
+    void iconChanged(const quint8 &icon);
+    void emergencyChanged(const bool emergency);
+
+private slots:
+    void propertyChanged(const QString &property, const QVariant &value);
+    void answerResp();
+    void answerErr(const QDBusError &error);
+    void hangupResp();
+    void hangupErr(const QDBusError &error);
+    void deflectResp();
+    void deflectErr(const QDBusError &error);
+
+private:
+    OfonoInterface *m_if;
+
+};
+
+#endif // OFONOVOICECALL_H
diff --git a/tests/test_ofonovoicecall.cpp b/tests/test_ofonovoicecall.cpp
new file mode 100644 (file)
index 0000000..45ca8db
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * This file is part of ofono-qt
+ *
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: Alexander Kanavin <alexander.kanavin@nokia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <QtTest/QtTest>
+#include <QtCore/QObject>
+
+#include <ofonovoicecallmanager.h>
+#include <ofonovoicecall.h>
+#include <QtDebug>
+
+
+class TestOfonoVoiceCall : public QObject
+{
+    Q_OBJECT
+
+private slots:
+    void initTestCase()
+    {
+        m = new OfonoVoiceCallManager(OfonoModem::ManualSelect, "/phonesim", this);
+        QCOMPARE(m->modem()->isValid(), true);
+        if (!m->modem()->powered()) {
+            m->modem()->setPowered(true);
+            QTest::qWait(5000);
+        }
+        if (!m->modem()->online()) {
+            m->modem()->setOnline(true);
+            QTest::qWait(5000);
+        }
+        QCOMPARE(m->isValid(), true);
+    }
+
+    void testOfonoVoiceCall()
+    {
+        QSignalSpy dialreg(m,SIGNAL(dialComplete(bool)));
+        QSignalSpy dspy(m, SIGNAL(callAdded(QString)));
+
+        // Dial and hangup
+        m->dial("123","");
+        QTest::qWait(1000);
+
+        QCOMPARE(dialreg.count(), 1);
+        QCOMPARE(dialreg.takeFirst().at(0).toBool(),true);
+        QCOMPARE(dspy.count(), 1);
+        QString callid = dspy.takeFirst().at(0).toString();
+
+        OfonoVoiceCall* call = new OfonoVoiceCall(callid);
+
+        QSignalSpy state(call, SIGNAL(stateChanged(const QString)));
+        QSignalSpy discreason(call,SIGNAL(disconnectReason(const QString)));
+        QSignalSpy hspy(call, SIGNAL(hangupComplete(bool)));
+        QSignalSpy li (call, SIGNAL(lineIdentificationChanged(QString)));
+        QSignalSpy name (call, SIGNAL(nameChanged(QString)));
+        QSignalSpy info (call, SIGNAL(informationChanged(QString)));
+        QSignalSpy mp (call, SIGNAL(multipartyChanged(bool)));
+        QSignalSpy em (call, SIGNAL(emergencyChanged(bool)));
+        QSignalSpy st (call, SIGNAL(startTimeChanged(QString)));
+        QSignalSpy ic (call, SIGNAL(iconChanged(quint8)));
+
+        QTest::qWait(10000);
+
+        QVERIFY(state.count()>0);
+        QVERIFY(st.count()>0);
+        QVERIFY(ic.count()==0);
+        QVERIFY(em.count()==0);
+        QVERIFY(mp.count()==0);
+        QVERIFY(info.count()==0);
+        QVERIFY(name.count()==0);
+        QVERIFY(li.count()==0);
+
+        QCOMPARE(call->state(),QString("active"));
+        QCOMPARE(call->lineIdentification(),QString("123"));
+        QCOMPARE(call->emergency(),false);
+        QCOMPARE(call->multiparty(),false);
+        QCOMPARE(call->name(),QString(""));
+        QCOMPARE(call->information(),QString(""));
+
+        call->hangup();
+        QTest::qWait(5000);
+        QCOMPARE(hspy.count(), 1);
+        QCOMPARE(hspy.takeFirst().at(0).toBool(),true);
+        QCOMPARE(discreason.count(), 1);
+        QCOMPARE(discreason.takeFirst().at(0).toString(), QString("local"));
+        delete call;
+    }
+
+    void testOfonoVoiceCallStep2()
+    {
+        //Dial failure, incoming, answer and local hangup
+        QSignalSpy callsignal(m, SIGNAL(callAdded(const QString)));
+
+        m->dial("199","");
+        QTest::qWait(8000);
+
+        QCOMPARE(callsignal.count(),1);
+        QString callid = callsignal.takeFirst().at(0).toString();
+
+        OfonoVoiceCall* call = new OfonoVoiceCall(callid);
+        QSignalSpy state(call, SIGNAL(stateChanged(const QString)));
+        QSignalSpy time(call,SIGNAL(startTimeChanged(const QString)));
+        QSignalSpy discreason(call,SIGNAL(disconnectReason(const QString)));
+        QSignalSpy hspy(call, SIGNAL(hangupComplete(bool)));
+        QSignalSpy aspy(call, SIGNAL(answerComplete(bool)));
+
+        QSignalSpy li (call, SIGNAL(lineIdentificationChanged(QString)));
+        QSignalSpy name (call, SIGNAL(nameChanged(QString)));
+        QSignalSpy info (call, SIGNAL(informationChanged(QString)));
+        QSignalSpy mp (call, SIGNAL(multipartyChanged(bool)));
+        QSignalSpy em (call, SIGNAL(emergencyChanged(bool)));
+        QSignalSpy ic (call, SIGNAL(iconChanged(quint8)));
+
+
+        QTest::qWait(8000);
+        QCOMPARE(call->state(),QString("incoming"));
+        call->answer();
+        QTest::qWait(10000);
+        QVERIFY(state.count()>0);
+        QCOMPARE(call->lineIdentification(),QString("1234567")); //PhoneSim specific value
+        QVERIFY(time.count()>0);
+        QCOMPARE(aspy.count(), 1);
+        QCOMPARE(aspy.takeFirst().at(0).toBool(),true);
+
+        QVERIFY(ic.count()==0);
+        QVERIFY(em.count()==0);
+        QVERIFY(mp.count()==0);
+        QVERIFY(info.count()==0);
+        QVERIFY(name.count()==0);
+        QVERIFY(li.count()==0);
+
+        call->hangup();
+        QTest::qWait(5000);
+        QCOMPARE(hspy.count(), 1);
+        QCOMPARE(hspy.takeFirst().at(0).toBool(), true);
+        QCOMPARE(discreason.count(), 1);
+        QCOMPARE(discreason.takeFirst().at(0).toString(), QString("local"));
+        delete call;
+    }
+
+    void testOfonoVoiceCallStep3()
+    {
+        //Dial failed, incoming, no answer and state change to disconnect
+        QSignalSpy callsignal(m, SIGNAL(callAdded(const QString)));
+
+        m->dial("177","");
+        QTest::qWait(3000);
+
+        QCOMPARE(callsignal.count(),1);
+        QString callid = callsignal.takeFirst().at(0).toString();
+
+        OfonoVoiceCall* call = new OfonoVoiceCall(callid);
+        QSignalSpy state(call, SIGNAL(stateChanged(const QString)));
+        QSignalSpy discreason(call,SIGNAL(disconnectReason(const QString)));
+
+        QTest::qWait(1000);
+        QCOMPARE(call->state(),QString("incoming"));
+        QTest::qWait(8000);
+        QVERIFY(state.count()>0);
+        QCOMPARE(discreason.count(), 1);
+        QCOMPARE(discreason.takeFirst().at(0).toString(), QString("remote"));
+        delete call;
+
+    }
+    void testOfonoVoiceCallStep4()
+    {
+        //Deflect
+        QSignalSpy callsignal(m, SIGNAL(callAdded(const QString)));
+        m->dial("199","");
+        QTest::qWait(8000);
+
+        QCOMPARE(callsignal.count(),1);
+        QString callid = callsignal.takeFirst().at(0).toString();
+
+        OfonoVoiceCall* call = new OfonoVoiceCall(callid);
+        QSignalSpy dfspy(call, SIGNAL(deflectComplete(bool)));
+
+        QTest::qWait(8000);
+        QCOMPARE(call->state(),QString("incoming"));
+        QCOMPARE(call->lineIdentification(),QString("1234567")); //PhoneSim specific value
+        call->deflect("2345");
+        QTest::qWait(8000);
+        QCOMPARE(dfspy.count(), 1);
+        QCOMPARE(dfspy.takeFirst().at(0).toBool(), true);
+        QTest::qWait(10000);
+
+        delete call;
+
+    }
+    void cleanupTestCase()
+    {
+
+    }
+
+
+private:
+    OfonoVoiceCallManager *m;
+};
+
+QTEST_MAIN(TestOfonoVoiceCall)
+#include "test_ofonovoicecall.moc"
diff --git a/tests/test_ofonovoicecall.pro b/tests/test_ofonovoicecall.pro
new file mode 100644 (file)
index 0000000..55dfa93
--- /dev/null
@@ -0,0 +1,2 @@
+include(testcase.pri)
+SOURCES += test_ofonovoicecall.cpp
index 4f62fe5..7bd8cba 100644 (file)
@@ -16,3 +16,4 @@ SUBDIRS += test_ofononetworkoperator.pro
 SUBDIRS += test_ofononetworkregistration.pro
 SUBDIRS += test_ofonosupplementaryservices.pro
 SUBDIRS += test_ofonovoicecallmanager.pro
+SUBDIRS += test_ofonovoicecall.pro