[PATCH] osmo-gsm-tester[master]: modem: Implement voice calls in modem and add voice suite

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Pau Espin Pedrol gerrit-no-reply at lists.osmocom.org
Fri Oct 13 15:50:21 UTC 2017


Hello Neels Hofmeyr, Harald Welte, Jenkins Builder,

I'd like you to reexamine a change.  Please visit

    https://gerrit.osmocom.org/4150

to look at the new patch set (#2).

modem: Implement voice calls in modem and add voice suite

Change-Id: Ib402effc830db293f27a877658894e454a93a606
---
M example/resources.conf
M src/osmo_gsm_tester/ofono_client.py
M src/osmo_gsm_tester/schema.py
A suites/voice/mo_mt_call.py
A suites/voice/suite.conf
5 files changed, 145 insertions(+), 3 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/osmo-gsm-tester refs/changes/50/4150/2

diff --git a/example/resources.conf b/example/resources.conf
index 3daf677..70c1c35 100644
--- a/example/resources.conf
+++ b/example/resources.conf
@@ -60,7 +60,7 @@
   ki: '80A37E6FDEA931EAC92FFA5F671EFEAD'
   auth_algo: 'xor'
   ciphers: [a5_0, a5_1]
-  features: ['sms']
+  features: ['sms', 'voice']
 
 - label: sierra_2
   path: '/sierra_2'
@@ -68,7 +68,7 @@
   ki: '00969E283349D354A8239E877F2E0866'
   auth_algo: 'xor'
   ciphers: [a5_0, a5_1]
-  features: ['sms']
+  features: ['sms', 'voice']
 
 - label: gobi_0
   path: '/gobi_0'
diff --git a/src/osmo_gsm_tester/ofono_client.py b/src/osmo_gsm_tester/ofono_client.py
index e301ed6..66c0a79 100644
--- a/src/osmo_gsm_tester/ofono_client.py
+++ b/src/osmo_gsm_tester/ofono_client.py
@@ -37,6 +37,8 @@
 I_MODEM = 'org.ofono.Modem'
 I_NETREG = 'org.ofono.NetworkRegistration'
 I_SMS = 'org.ofono.MessageManager'
+I_CALLMGR = 'org.ofono.VoiceCallManager'
+I_CALL = 'org.ofono.VoiceCall'
 
 # See https://github.com/intgr/ofono/blob/master/doc/network-api.txt#L78
 NETREG_ST_REGISTERED = 'registered'
@@ -338,11 +340,15 @@
         self.sms_received_list = []
         self.dbus = ModemDbusInteraction(self.path)
         self.register_attempts = 0
+        self.call_list = []
         # one Cancellable can handle several concurrent methods.
         self.cancellable = Gio.Cancellable.new()
         self.dbus.required_signals = {
                 I_SMS: ( ('IncomingMessage', self._on_incoming_message), ),
                 I_NETREG: ( ('PropertyChanged', self._on_netreg_property_changed), ),
+                I_CALLMGR: ( ('PropertyChanged', self._on_callmgr_property_changed),
+                              ('CallAdded', self._on_callmgr_call_added),
+                              ('CallRemoved', self._on_callmgr_call_removed), ),
             }
         self.dbus.watch_interfaces()
 
@@ -558,6 +564,80 @@
                 return True
         return False
 
+    def call_id_list(self):
+        self.dbg('call_id_list: %r' % self.call_list)
+        return self.call_list
+
+    def call_dial(self, to_msisdn_or_modem):
+        if isinstance(to_msisdn_or_modem, Modem):
+            to_msisdn = to_msisdn_or_modem.msisdn
+        else:
+            to_msisdn = str(to_msisdn_or_modem)
+        self.dbg('Dialing:', to_msisdn)
+        cmgr = self.dbus.interface(I_CALLMGR)
+        call_obj_path = cmgr.Dial(to_msisdn, 'default')
+        if call_obj_path not in self.call_list:
+            self.dbg('Adding %s to call list' % call_obj_path)
+            self.call_list.append(call_obj_path)
+        else:
+            self.dbg('Dial returned already existing call')
+        return call_obj_path
+
+    def _find_call_msisdn_state(self, msisdn, state):
+        cmgr = self.dbus.interface(I_CALLMGR)
+        ret = cmgr.GetCalls()
+        for obj_path, props in ret:
+            if props['LineIdentification'] == msisdn and props['State'] == state:
+                return obj_path
+        return None
+
+    def call_wait_incoming(self, caller_msisdn_or_modem, timeout=60):
+        if isinstance(caller_msisdn_or_modem, Modem):
+            caller_msisdn = caller_msisdn_or_modem.msisdn
+        else:
+            caller_msisdn = str(caller_msisdn_or_modem)
+        self.dbg('Waiting for incoming call from:', caller_msisdn)
+        event_loop.wait(self, lambda: self._find_call_msisdn_state(caller_msisdn, 'incoming') is not None, timeout=timeout)
+        return self._find_call_msisdn_state(caller_msisdn, 'incoming')
+
+    def call_answer(self, call_id):
+        self.dbg('Answer call %s' % call_id)
+        assert self.call_state(call_id) == 'incoming'
+        call_dbus_obj = systembus_get(call_id)
+        call_dbus_obj.Answer()
+
+    def call_hangup(self, call_id):
+        self.dbg('Hang up call %s' % call_id)
+        call_dbus_obj = systembus_get(call_id)
+        call_dbus_obj.Hangup()
+
+    def call_is_active(self, call_id):
+        return self.call_state(call_id) == 'active'
+
+    def call_state(self, call_id):
+        call_dbus_obj = systembus_get(call_id)
+        props = call_dbus_obj.GetProperties()
+        state = props.get('State')
+        self.dbg('call state: %s' % state)
+        return state
+
+    def _on_callmgr_call_added(self, obj_path, properties):
+        self.dbg('%r.CallAdded() -> %s=%r' % (I_CALLMGR, obj_path, repr(properties)))
+        if obj_path not in self.call_list:
+            self.call_list.append(obj_path)
+        else:
+            self.dbg('Call already exists %r' % obj_path)
+
+    def _on_callmgr_call_removed(self, obj_path):
+        self.dbg('%r.CallRemoved() -> %s' % (I_CALLMGR, obj_path))
+        if obj_path in self.call_list:
+            self.call_list.remove(obj_path)
+        else:
+            self.dbg('Trying to remove non-existing call %r' % obj_path)
+
+    def _on_callmgr_property_changed(self, name, value):
+        self.dbg('%r.PropertyChanged() -> %s=%s' % (I_CALLMGR, name, value))
+
     def info(self, keys=('Manufacturer', 'Model', 'Revision', 'Serial')):
         props = self.properties()
         return ', '.join(['%s: %r'%(k,props.get(k)) for k in keys])
diff --git a/src/osmo_gsm_tester/schema.py b/src/osmo_gsm_tester/schema.py
index 6d5f7ad..9b142d3 100644
--- a/src/osmo_gsm_tester/schema.py
+++ b/src/osmo_gsm_tester/schema.py
@@ -82,7 +82,7 @@
     raise ValueError('Unknown Cipher value: %r' % val)
 
 def modem_feature(val):
-    if val in ('sms', 'gprs', 'voicecall', 'ussd'):
+    if val in ('sms', 'gprs', 'voice', 'ussd'):
         return
     raise ValueError('Unknown Modem Feature: %r' % val)
 
diff --git a/suites/voice/mo_mt_call.py b/suites/voice/mo_mt_call.py
new file mode 100755
index 0000000..f426037
--- /dev/null
+++ b/suites/voice/mo_mt_call.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python3
+from osmo_gsm_tester.test import *
+
+hlr = suite.hlr()
+bts = suite.bts()
+mgcpgw = suite.mgcpgw(bts_ip=bts.remote_addr())
+msc = suite.msc(hlr, mgcpgw)
+bsc = suite.bsc(msc)
+stp = suite.stp()
+ms_mo = suite.modem()
+ms_mt = suite.modem()
+
+hlr.start()
+stp.start()
+msc.start()
+mgcpgw.start()
+
+bsc.bts_add(bts)
+bsc.start()
+
+bts.start()
+
+hlr.subscriber_add(ms_mo)
+hlr.subscriber_add(ms_mt)
+
+ms_mo.connect(msc.mcc_mnc())
+ms_mt.connect(msc.mcc_mnc())
+
+ms_mo.log_info()
+ms_mt.log_info()
+
+print('waiting for modems to attach...')
+wait(ms_mo.is_connected, msc.mcc_mnc())
+wait(ms_mt.is_connected, msc.mcc_mnc())
+wait(msc.subscriber_attached, ms_mo, ms_mt)
+
+assert len(ms_mo.call_id_list()) == 0 and len(ms_mt.call_id_list()) == 0
+mo_cid = ms_mo.call_dial(ms_mt)
+mt_cid = ms_mt.call_wait_incoming(ms_mo)
+print('dial success')
+
+assert not ms_mo.call_is_active(mo_cid) and not ms_mt.call_is_active(mt_cid)
+ms_mt.call_answer(mt_cid)
+wait(ms_mo.call_is_active, mo_cid)
+wait(ms_mt.call_is_active, mt_cid)
+print('answer success, call established and ongoing')
+
+sleep(5) # maintain the call active for 5 seconds
+
+assert ms_mo.call_is_active(mo_cid) and ms_mt.call_is_active(mt_cid)
+ms_mt.call_hangup(mt_cid)
+wait(lambda: len(ms_mo.call_id_list()) == 0 and len(ms_mt.call_id_list()) == 0)
+print('hangup success')
diff --git a/suites/voice/suite.conf b/suites/voice/suite.conf
new file mode 100644
index 0000000..40d9f97
--- /dev/null
+++ b/suites/voice/suite.conf
@@ -0,0 +1,9 @@
+resources:
+  ip_address:
+  - times: 5 # msc, bsc, hlr, stp, mgw
+  bts:
+  - times: 1
+  modem:
+  - times: 2
+    features:
+    - voice

-- 
To view, visit https://gerrit.osmocom.org/4150
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newpatchset
Gerrit-Change-Id: Ib402effc830db293f27a877658894e454a93a606
Gerrit-PatchSet: 2
Gerrit-Project: osmo-gsm-tester
Gerrit-Branch: master
Gerrit-Owner: Pau Espin Pedrol <pespin at sysmocom.de>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: Neels Hofmeyr <nhofmeyr at sysmocom.de>
Gerrit-Reviewer: Pau Espin Pedrol <pespin at sysmocom.de>



More information about the gerrit-log mailing list