In this series, we will review the codes in mobileInsight-desktop,
the core modules and desktop version of MobileInsight. Following the
discussions in Part-I, this article introduces
analyzers, the core modules in MobileInsight for cellular protocol
analytics. Besides, we will also introduce other misc modules in
mobileInsight-desktop.

Given cellular messages from Monitors, MobileInsight further
triggers analyzers to perform diverse cellular analytics. We have
realized various analyzers, all of which are included in
mobile_insight/analyzer, as shown below (this list still goes on and
long):

Some common analyzers are summarized as below. Note that to develop a
cellular protocol analyzer, it is usually required to have a
comprehensive understanding of the 3G/4G cellular protocols. This
requires to read 3GPP standards, as listed below. Instead of elaborating
the protocol-specific analytics, this article will focus on the common
APIs, conventions, and structures of an analyzer. We next elaborate it.

All MobileInsight analyzers should inherit from the base class
Analyzers, which defines the basic interface for a monitor: -
Declare its dependency on cellular message types: enable_log; -
Declare its dependency on other analyzers: include_analyzer; - Bind
to a monitor: set_source; - Callbacks in response to events from
monitor (add_source_callback) or other analyzers
(include_analyzer); - (Optional) pushes runtime cellular information
to other mobile apps (with MI-APPAPI).

Each analyzer should overload these interfaces based on its specific
environment. The following code snippet summaries the abstract
interfaces (complete code in mobile_insight/monitor/analyzer.py):

from..elementimportElement,EventclassAnalyzer(Element):def__init__(self):Element.__init__(self)""" Task lists 1. Initialize empty monitor 2. Initialize empty list of callbacks for monitor and other analyzers """# ...defset_source(self,source):""" Bind this analyzer to a monitor (source) The messages from the source will drive the analysis. All parent analyzers this analyzer depends on will also be recursively bound to source """defadd_source_callback(self,callback):""" Add a callback function to the analyzer. When a message arrives, the analyzer will trigger the callbacks for analysis. """defrm_source_callback(self,callback):""" Delete a callback function to the analyzer. """definclude_analyzer(self,analyzer_name,callback_list,*args):""" Declares the dependency from other analyzers. Once declared, the current analyzer will receive events from other analyzers, then trigger functions in callback_list """defrecv(self,module,event):""" Handle the received events. This is an overload member from Element """

In the following, we will use one example LtePhyAnalyzer to show how
to develop your own analyzer, and overload above interfaces.

An analyzer should declare the cellular messages it need for protocol
analytics. This is realized by calling enable_log, which is
typically called when binding the analyzer to the monitor. In this
way, the monitor will activate the corresponding message collection at
hardware, and pushes this message to analyzer by calling the source
callbacks (registered via add_source_callback).

The following shows one example of how to achieve it. In writing a new
analyzer, we should overload set_source to include supported message
types, and register the callback in __init__ initialization
function.

In many cases, your analyzer can be built on top of existing analyzers,
thus reusing their analytical results. This modular approach simplifies
the development, and makes code reusing possible. Typically, to declare
the dependency of an analyzer (i.e., “parent analyzer”), your analyzer
should call include_analyzer during the initialization (in
__init__), and passes a callback function in response to these
analyzer’s events. The following code shows how it works:

For both monitor and parent analyzer, an analyzer should provide a
callback function in response to their cellular events. These callbacks
are registered when binding to a monitor (add_source_callback), or
declaring a parent analyzer (include_analyzer). In both cases, the
callback takes one parameter msg as input, which is the event raised
by monitor or parent analyzer. Inside the callback, you can decode this
message, and perform specific analytics tasks.

The following shows the cellular message callback in LtePhyAnalyzer.
This callback is triggered by cellular messages from Monitor. It
first determines the message type, decode the messages, then take
specific actions.

Besides event-driven callbacks, the analyzer also provides another
interface to push analytics results to other mobile apps. This is called
MI-APPAPI. To learn how to use it, you can read the following
tutorial:

ws_dissector is simply a wrapper of Wireshark’s parsing functions.
It is called by DmLogPacket (which calls WSDissector in
`mobile_insight/monitor/dm_collector/dm_endec/ws_dissector.py) to
parse cellular messages. The structure is as follows:

MobileInsight leverages the standardized Python setup scripts to package
its desktop-version modules. It has two files:

“MANIFEST.in“: it specifies which files to be included, which
files should not be included (such as dm_collector_c). It follows
the standardized Python setup script format, as shown below
(mobileInsight-desktop/MANIFEST.in):