From 57edd23065c486465ef4ad068c933fd08b8d2299 Mon Sep 17 00:00:00 2001 From: Haotian Deng Date: Sun, 23 Jul 2017 21:33:56 -0400 Subject: [PATCH 1/7] Add stop mechanism for plugins --- app/main.py | 33 ++++++++++++++++-- app/plugins/NasAnalysis/main.mi2app | 22 +++++++++++- app/plugins/NetLogger/logging_analyzer.py | 41 +++++++++++++++++------ app/plugins/NetLogger/main.mi2app | 0 app/plugins/RrcAnalysis/main.mi2app | 22 +++++++++++- 5 files changed, 103 insertions(+), 15 deletions(-) mode change 100755 => 100644 app/plugins/NetLogger/logging_analyzer.py mode change 100755 => 100644 app/plugins/NetLogger/main.mi2app diff --git a/app/main.py b/app/main.py index c960f93..e3aaccc 100644 --- a/app/main.py +++ b/app/main.py @@ -32,11 +32,13 @@ import shutil import stat import json +import datetime import main_utils from log_viewer_app import LogViewerScreen from collections import deque +from android.broadcast import BroadcastReceiver # Load main UI Window.softinput_mode = "pan" @@ -532,8 +534,34 @@ def start_service(self, app_name): else: self.error_log = "Error: " + app_name + "cannot be launched!" + def on_broadcastStopServiceAck(self, context, intent): + self.log_info("Received MobileInsight.Plugin.StopServiceAck from plugin") + self.pluginAck = True + def stop_service(self): + # Registe listener for 'MobileInsight.Plugin.StopServiceAck' intent + # from plugin + self.log_info("Ready to stop current plugin ...") + self.pluginAck = False + self.br = BroadcastReceiver(self.on_broadcastStopServiceAck, + actions=['MobileInsight.Plugin.StopServiceAck']) + self.br.start() + + # Using broadcast to send 'MobileInsight.Main.StopService' intent to + # plugin + IntentClass = autoclass("android.content.Intent") + intent = IntentClass() + action = 'MobileInsight.Main.StopService' + intent.setAction(action) + try: + current_activity.sendBroadcast(intent) + except Exception as e: + import traceback + self.log_error(str(traceback.format_exc())) + if self.service: + while (not self.pluginAck): + pass self.service.stop() self.service = None if self.terminal_stop: @@ -543,7 +571,7 @@ def stop_service(self): "Plugin stopped. Detailed analytic results are saved in " + self.log_name) - self.stop_collection() # close ongoing collections + self.stop_collection() # close ongoing collections (diag_revealer) # Haotian: save orphan log dated_files = [] @@ -558,8 +586,7 @@ def stop_service(self): dated_files.reverse() if len(dated_files) > 0: self.__original_filename = dated_files[0][1] - # print "The last orphan log file: " + - # str(self.__original_filename) + print "Find orphan log file at Main: " + str(self.__original_filename) chmodcmd = "chmod 644 " + self.__original_filename p = subprocess.Popen( "su ", diff --git a/app/plugins/NasAnalysis/main.mi2app b/app/plugins/NasAnalysis/main.mi2app index 14c6828..93102b7 100755 --- a/app/plugins/NasAnalysis/main.mi2app +++ b/app/plugins/NasAnalysis/main.mi2app @@ -3,10 +3,30 @@ import os import sys # Import MobileInsight modules -from mobile_insight.monitor import OnlineMonitor +from android.broadcast import BroadcastReceiver +from jnius import autoclass from mobile_insight.analyzer import LteNasAnalyzer, UmtsNasAnalyzer +from mobile_insight.monitor import OnlineMonitor import mi2app_utils +def on_broadcast(context, intent): + ''' + This plugin is going to be stopped, finish closure work + ''' + IntentClass = autoclass("android.content.Intent") + intent = IntentClass() + action = 'MobileInsight.Plugin.StopServiceAck' + intent.setAction(action) + try: + mi2app_utils.pyService.sendBroadcast(intent) + except Exception as e: + import traceback + lte_nas_analyzer.log_error(str(traceback.format_exc())) + +br = BroadcastReceiver( + on_broadcast, actions=['MobileInsight.Main.StopService']) +br.start() + cache_directory = mi2app_utils.get_cache_dir() log_directory = os.path.join(cache_directory, "mi2log") diff --git a/app/plugins/NetLogger/logging_analyzer.py b/app/plugins/NetLogger/logging_analyzer.py old mode 100755 new mode 100644 index a9e1f79..a878f09 --- a/app/plugins/NetLogger/logging_analyzer.py +++ b/app/plugins/NetLogger/logging_analyzer.py @@ -11,21 +11,23 @@ 1.0 Init NetLogger ''' -import os -import time -import shutil -import urllib -import urllib2 -import logging + +from android.broadcast import BroadcastReceiver +from jnius import autoclass +from mobile_insight.analyzer import Analyzer import datetime import itertools +import logging +import mi2app_utils as util import mimetools import mimetypes -import threading +import os +import shutil import subprocess - -from mobile_insight.analyzer import Analyzer -import mi2app_utils as util +import threading +import time +import urllib +import urllib2 # logging.basicConfig(level=logging.DEBUG, # format='[%(levelname)s] (%(threadName)-10s) %(message)s', @@ -174,6 +176,25 @@ def __init__(self, config): self.add_source_callback(self._logger_filter) + self.br = BroadcastReceiver(self.on_broadcast, + actions=['MobileInsight.Main.StopService']) + self.br.start() + + def on_broadcast(self, context, intent): + ''' + This plugin is going to be stopped, finish closure work + ''' + IntentClass = autoclass("android.content.Intent") + intent = IntentClass() + action = 'MobileInsight.Plugin.StopServiceAck' + intent.setAction(action) + try: + util.pyService.sendBroadcast(intent) + except Exception as e: + import traceback + self.log_error(str(traceback.format_exc())) + + def __del__(self): self.log_info("__del__ is called") diff --git a/app/plugins/NetLogger/main.mi2app b/app/plugins/NetLogger/main.mi2app old mode 100755 new mode 100644 diff --git a/app/plugins/RrcAnalysis/main.mi2app b/app/plugins/RrcAnalysis/main.mi2app index 30c2887..c134e21 100644 --- a/app/plugins/RrcAnalysis/main.mi2app +++ b/app/plugins/RrcAnalysis/main.mi2app @@ -3,10 +3,30 @@ import os import sys # Import MobileInsight modules -from mobile_insight.monitor import OnlineMonitor +from android.broadcast import BroadcastReceiver +from jnius import autoclass from mobile_insight.analyzer import LteRrcAnalyzer, WcdmaRrcAnalyzer +from mobile_insight.monitor import OnlineMonitor import mi2app_utils +def on_broadcast(context, intent): + ''' + This plugin is going to be stopped, finish closure work + ''' + IntentClass = autoclass("android.content.Intent") + intent = IntentClass() + action = 'MobileInsight.Plugin.StopServiceAck' + intent.setAction(action) + try: + mi2app_utils.pyService.sendBroadcast(intent) + except Exception as e: + import traceback + lte_rrc_analyzer.log_error(str(traceback.format_exc())) + +br = BroadcastReceiver( + on_broadcast, actions=['MobileInsight.Main.StopService']) +br.start() + cache_directory = mi2app_utils.get_cache_dir() log_directory = os.path.join(cache_directory, "mi2log") From 34e56d6f44c5c793f3afa5be57f6954ef1e734c8 Mon Sep 17 00:00:00 2001 From: Haotian Deng Date: Mon, 24 Jul 2017 01:36:12 -0400 Subject: [PATCH 2/7] Plugins will be forced to stop if waiting time since user click stop button is longer than 5 seconds --- app/main.py | 52 +++++++++++++++++++++++++--------------------------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/app/main.py b/app/main.py index 290ac47..0ba4dc8 100644 --- a/app/main.py +++ b/app/main.py @@ -1,44 +1,39 @@ import kivy kivy.require('1.0.9') -from kivy.uix.screenmanager import ScreenManager, Screen -from kivy.uix.gridlayout import GridLayout -from kivy.uix.scrollview import ScrollView -from kivy.uix.popup import Popup -from kivy.uix.label import Label -from kivy.uix.button import Button -from kivy.properties import * +from android import AndroidService +from android.broadcast import BroadcastReceiver +from collections import deque +from jnius import autoclass, cast from kivy.app import App from kivy.clock import Clock +from kivy.config import ConfigParser from kivy.core.window import Window from kivy.lang import Builder +from kivy.properties import * +from kivy.uix.button import Button +from kivy.uix.gridlayout import GridLayout +from kivy.uix.label import Label +from kivy.uix.popup import Popup +from kivy.uix.screenmanager import ScreenManager, Screen +from kivy.uix.scrollview import ScrollView from kivy.utils import platform -from kivy.config import ConfigParser - -from android import AndroidService -from jnius import autoclass, cast -import jnius - +from log_viewer_app import LogViewerScreen +import datetime import functools +import jnius +import json +import main_utils import os +import re import shlex -import sys +import shutil +import stat import subprocess +import sys import threading import time import traceback -import re -import datetime -import shutil -import stat -import json -import datetime - -import main_utils -from log_viewer_app import LogViewerScreen - -from collections import deque -from android.broadcast import BroadcastReceiver # Load main UI Window.softinput_mode = "pan" @@ -566,7 +561,10 @@ def stop_service(self): self.log_error(str(traceback.format_exc())) if self.service: - while (not self.pluginAck): + start_time = datetime.datetime.utcnow() + current_time = datetime.datetime.utcnow() + while (not self.pluginAck and (current_time - start_time).total_seconds() < 5): + current_time = datetime.datetime.utcnow() pass self.service.stop() self.service = None From d29f29a8ca97ad34c8dc2e531ca13df4af4b87b1 Mon Sep 17 00:00:00 2001 From: Haotian Deng Date: Tue, 8 Aug 2017 08:58:51 -0400 Subject: [PATCH 3/7] Invoke tcpdump in app/main.py --- app/main.py | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/app/main.py b/app/main.py index a492729..97c266d 100644 --- a/app/main.py +++ b/app/main.py @@ -233,6 +233,8 @@ def __init__(self, name): my_description = "no description." widget.text = name + ": " + my_description + self.registerBroadcastReceivers() + # If default service exists, launch it try: config = ConfigParser() @@ -243,12 +245,17 @@ def __init__(self, name): self.start_service(default_app_name) except Exception as e: pass + + def registerBroadcastReceivers(self): + self.brStopAck = BroadcastReceiver(self.on_broadcastStopServiceAck, + actions=['MobileInsight.Plugin.StopServiceAck']) + self.brStopAck.start() + def callback(self, obj): self.selectedPlugin = obj.text[0:obj.text.find(":")] self.ids.selectButton.text = "Select Plugin: " + self.selectedPlugin #self.ids.run_plugin.text = "Run Plugin: " + self.selectedPlugin self.popup.dismiss() - def log_info(self, msg): self.append_log("[b][color=00ff00][INFO][/color][/b]: " + msg) @@ -530,6 +537,13 @@ def start_service(self, app_name): app_name + ":" + self.plugins_list[app_name][0]) # app name self.default_app_name = app_name + # Run TCPDUMP binary + currentTime = datetime.datetime.now().strftime('%Y%m%d_%H%M%S') + tcpdumpcmd = "su -c tcpdump -i rmnet_data0 -w " \ + + main_utils.get_mobileinsight_log_path() \ + + "/tcpdump_" + str(currentTime) + ".pcap\n" + main_utils.run_shell_cmd() + else: self.error_log = "Error: " + app_name + "cannot be launched!" @@ -542,9 +556,6 @@ def stop_service(self): # from plugin self.log_info("Ready to stop current plugin ...") self.pluginAck = False - self.br = BroadcastReceiver(self.on_broadcastStopServiceAck, - actions=['MobileInsight.Plugin.StopServiceAck']) - self.br.start() # Using broadcast to send 'MobileInsight.Main.StopService' intent to # plugin @@ -575,7 +586,11 @@ def stop_service(self): self.stop_collection() # close ongoing collections (diag_revealer) - # Haotian: save orphan log + # killall tcpdump + tcpdumpcmd = "su -c killall tcpdump\n" + main_utils.run_shell_cmd(tcpdumpcmd) + + # Save orphan log dated_files = [] self.__logdir = main_utils.get_mobileinsight_log_path() self.__phone_info = main_utils.get_phone_info() From d878fde244b8f559ce2a7239c73bfd53a8dd3360 Mon Sep 17 00:00:00 2001 From: Haotian Deng Date: Wed, 30 Aug 2017 20:21:29 -0400 Subject: [PATCH 4/7] Fix old path caused by 3.0 update in .gitignore file --- .gitignore | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index e59cf63..15e1dd1 100644 --- a/.gitignore +++ b/.gitignore @@ -40,9 +40,9 @@ dist/ *diag_revealer # Data directory -demo_app/data/* +app/data/* # Not filter files -!demo_app/data/MTK-filter +!app/data/MTK-filter # Personalized config file config.yml* From f9ec6e55cd907047f05d7bf5871dc3f9f8d83690 Mon Sep 17 00:00:00 2001 From: Haotian Deng Date: Wed, 30 Aug 2017 20:31:25 -0400 Subject: [PATCH 5/7] Check orphan logs using stop machinism in logging analyzer --- app/main.py | 25 ----------------------- app/plugins/NetLogger/logging_analyzer.py | 21 +++++++++++++++++++ 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/app/main.py b/app/main.py index 3064695..b8ca4db 100644 --- a/app/main.py +++ b/app/main.py @@ -603,31 +603,6 @@ def stop_service(self): tcpdumpcmd = "su -c killall tcpdump\n" main_utils.run_shell_cmd(tcpdumpcmd) - # Save orphan log - dated_files = [] - self.__logdir = main_utils.get_mobileinsight_log_path() - self.__phone_info = main_utils.get_phone_info() - mi2log_folder = os.path.join(main_utils.get_cache_dir(), "mi2log") - for subdir, dirs, files in os.walk(mi2log_folder): - for f in files: - fn = os.path.join(subdir, f) - dated_files.append((os.path.getmtime(fn), fn)) - dated_files.sort() - dated_files.reverse() - if len(dated_files) > 0: - self.__original_filename = dated_files[0][1] - print "Find orphan log file at Main: " + str(self.__original_filename) - chmodcmd = "chmod 644 " + self.__original_filename - p = subprocess.Popen( - "su ", - executable=main_utils.ANDROID_SHELL, - shell=True, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE) - p.communicate(chmodcmd + '\n') - p.wait() - self._save_log() - def on_click_plugin(self, app_name): if self.service: self.stop_service() diff --git a/app/plugins/NetLogger/logging_analyzer.py b/app/plugins/NetLogger/logging_analyzer.py index a878f09..2fafcec 100644 --- a/app/plugins/NetLogger/logging_analyzer.py +++ b/app/plugins/NetLogger/logging_analyzer.py @@ -184,6 +184,9 @@ def on_broadcast(self, context, intent): ''' This plugin is going to be stopped, finish closure work ''' + self.log_info("MobileInsight.Main.StopService is received") + self._check_orphan_log() + IntentClass = autoclass("android.content.Intent") intent = IntentClass() action = 'MobileInsight.Plugin.StopServiceAck' @@ -194,6 +197,24 @@ def on_broadcast(self, context, intent): import traceback self.log_error(str(traceback.format_exc())) + def _check_orphan_log(self): + ''' + Check if there is any orphan log left in cache folder + ''' + dated_files = [] + mi2log_folder = os.path.join(util.get_cache_dir(), "mi2log") + for subdir, dirs, files in os.walk(mi2log_folder): + for f in files: + fn = os.path.join(subdir, f) + dated_files.append((os.path.getmtime(fn), fn)) + dated_files.sort() + dated_files.reverse() + for dated_file in dated_files: + self.__orig_file = dated_file[1] + self.log_info("LoggingAnalyzer: find orphan log: %s" % self.__orig_file) + util.run_shell_cmd("chmod 644 %s" % self.__orig_file) + self._save_log() + self.log_info("mi2log file saved") def __del__(self): self.log_info("__del__ is called") From 3b4d3d7f8d64271f2fd098c5d19043770596cb69 Mon Sep 17 00:00:00 2001 From: Haotian Deng Date: Wed, 30 Aug 2017 20:53:19 -0400 Subject: [PATCH 6/7] Fix bug when launching tcpdump --- app/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/main.py b/app/main.py index bf3853b..a09c1f9 100644 --- a/app/main.py +++ b/app/main.py @@ -554,7 +554,7 @@ def start_service(self, app_name): tcpdumpcmd = "su -c tcpdump -i rmnet_data0 -w " \ + main_utils.get_mobileinsight_log_path() \ + "/tcpdump_" + str(currentTime) + ".pcap\n" - main_utils.run_shell_cmd() + main_utils.run_shell_cmd(tcpdumpcmd) else: self.error_log = "Error: " + app_name + "cannot be launched!" From f6f1f2b3f4ec97ba843394fe177f021ed83694a1 Mon Sep 17 00:00:00 2001 From: Haotian Deng Date: Wed, 30 Aug 2017 22:58:51 -0400 Subject: [PATCH 7/7] Disable tcpdump need to specity different interface name for different devices --- app/main.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/app/main.py b/app/main.py index a09c1f9..33d8bca 100644 --- a/app/main.py +++ b/app/main.py @@ -541,7 +541,7 @@ def start_service(self, app_name): self.error_log = "Running " + app_name + "..." self.service = AndroidService( "MobileInsight is running...", app_name) - + # stop the running service self.service.stop() @@ -549,12 +549,12 @@ def start_service(self, app_name): app_name + ":" + self.plugins_list[app_name][0]) # app name self.default_app_name = app_name - # Run TCPDUMP binary - currentTime = datetime.datetime.now().strftime('%Y%m%d_%H%M%S') - tcpdumpcmd = "su -c tcpdump -i rmnet_data0 -w " \ - + main_utils.get_mobileinsight_log_path() \ - + "/tcpdump_" + str(currentTime) + ".pcap\n" - main_utils.run_shell_cmd(tcpdumpcmd) + # TODO: support collecting TCPDUMP trace + # currentTime = datetime.datetime.now().strftime('%Y%m%d_%H%M%S') + # tcpdumpcmd = "su -c tcpdump -i rmnet_data0 -w " \ + # + main_utils.get_mobileinsight_log_path() \ + # + "/tcpdump_" + str(currentTime) + ".pcap\n" + # main_utils.run_shell_cmd(tcpdumpcmd) else: self.error_log = "Error: " + app_name + "cannot be launched!" @@ -599,8 +599,8 @@ def stop_service(self): self.stop_collection() # close ongoing collections (diag_revealer) # killall tcpdump - tcpdumpcmd = "su -c killall tcpdump\n" - main_utils.run_shell_cmd(tcpdumpcmd) + # tcpdumpcmd = "su -c killall tcpdump\n" + # main_utils.run_shell_cmd(tcpdumpcmd) def on_click_plugin(self, app_name): if self.service: