Beispiel #1
0
class FlashApp(App):
    def build(self):
        self.root = Switch()
        self.service = AndroidService('Kivy FlashLight', 'I haz a FlashLight!')
        self.root.bind(active=self.toggle_flash)
        return self.root

    def toggle_flash(self, *args):
        if self.root.active:
            self.service.start()
        else:
            self.service.stop()
Beispiel #2
0
class RemoteKivyApp(App):
    def build(self):
        global app
        app = self
        self.service = AndroidService('Kivy Remote Shell',
                                      'remote shell is running')
        self.service.start('8000')
        return MainScreen()

    def quit_app(self):
        self.service.stop()
        self.stop()
Beispiel #3
0
class RemoteKivyApp(App):
    def build(self):
        global app
        app = self
        self.service = AndroidService('Kivy Remote Shell',
                                      'remote shell is running')
        self.service.start('8000')
        return MainScreen()

    def quit_app(self):
        self.service.stop()
        self.stop()
Beispiel #4
0
class ServiceExample(App):
    def start_service(self):
        # Make a thing to test passing vars to the service
        appdict = {"string": "Hello!", "int": 1, "list": [1, 2, 3, 4, 5]}
        # JSON. every. day.
        dumpd = dumps(appdict)
        # Makin' that service
        self.service = AndroidService('Sevice example', 'service is running')
        # This just starts the service. I shouldn't need a comment here.
        self.service.start(dumpd)

    def stop_service(self):
        self.service.stop()
Beispiel #5
0
class DjandroApp(App):
    def build(self):
        self.service = AndroidService('Django', 'Django is running')
        open(LOGPATH, 'w').close()  # Touch the logfile
        self.running = False
        self.logging = False
        
    def toggle(self):
        action = self.stop if self.running else self.start
        self.running = not self.running
        action()
        self.root.ids['info'].text = "[color=#ff0000]Django is OFF[/color]"
        if self.running:
            self.root.ids['info'].text = "[color=#00ff00]Django is ON[/color]"

        btn_text = 'Stop' if self.running else 'Start'
        self.root.ids['btn'].text = btn_text + " Django"

    def start(self):
        self.service.start(LOGPATH)
        self.start_logging()

    def stop(self):
        self.service.stop()
        self.logging = False
        self.running = False

    def start_logging(self):
        self.console = Thread(target=self.logger)
        self.logging = True
        self.console.start()

    def logger(self):
        label = self.root.ids['console']
        log = open(LOGPATH, 'r')
        label.text = log.read()
        while self.logging:
            log.seek(log.tell())
            label.text += log.read()
            sleep(0.2)

    def on_pause(self):
        if self.logging:
            self.logging = False
            self.console.join()
        return True


    def on_resume(self):
        if self.running:
            self.start_logging()
Beispiel #6
0
class ServiceExample(App):

    def start_service(self):
        # Make a thing to test passing vars to the service
        appdict = {"string": "Hello!",
                   "int": 1,
                   "list": [1,2,3,4,5]}
        # Makin' that service
        self.service = AndroidService('Sevice example', 'service is running')
        # This just starts the service. I shouldn't need a comment here.
        self.service.start(dumpd)

    def stop_service(self):
        self.service.stop()
Beispiel #7
0
class BestVibratorAppServiceController(object):

	def __init__(self, **kwargs):
		super(BestVibratorAppServiceController, self).__init__(**kwargs)
		self.SERVICE_ACTIVE=False
		if platform=="android":
			from android import AndroidService
			self.service=AndroidService("Best Vibrator Service", "running")
			self.service.start("Best Vibrator Service started")
			self.SERVICE_ACTIVE=True
		osc.init()
	
	def service_stop(self):
		self.service.stop()
		self.SERVICE_ACTIVE=False
Beispiel #8
0
class ServiceTestApp(App):
    def start_service(self):
        self.service = AndroidService('Sevice example', 'service is running')
        self.service.start('Hello From Service')

    def stop_service(self):
        self.service.stop()

    def on_start(self, *l):
        Logger.info('start')
        self.start_service()
        pass

    def on_stop(self, *l):
        Logger.info('stop')
        self.stop_service()

    def on_pause(self):
        return True

    def on_resume(self):
        pass
Beispiel #9
0
class PhotoRiverApp(App):
    flashair_uri = ""
    folder = ""
    album_name = ""

    def on_start(self):
        self.service = AndroidService()

    def start_service(self):
        service_args = dict(
            flashair_uri=self.flashair_uri,
            folder=self.folder,
            album_name=self.album_name,
        )
        self.service.start(json.dumps(service_args))

    def stop_service(self):
        self.service.stop()

    def on_pause(self):
        return True

    def on_resume(self):
        return True
Beispiel #10
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()
Beispiel #11
0
class MainWindow(Widget):
    destination = StringProperty('Unknown')
    currentstatus = StringProperty('not yet started')
    selectedDeviceName = StringProperty('Select device')
    isRunning = BooleanProperty(False)

    def __init__(self, **kwargs):
        if platform == 'android':
            self.isRunning = isServiceRunning()
            if self.isRunning:
                self.service = AndroidService('my gps service', 'running')
                self.currentstatus = "service was running"
            else:
                self.service = None
        else:
            self.service = None
            self.isRunning = False
        super(MainWindow, self).__init__(**kwargs)

    def getSettings(self):
        self.config = ConfigParser()
        if self.config.read(appConfigFileName):
            if self.config.has_option('general', 'device'):
                self.device = self.config.get('general', 'device')
            else:
                self.device = None
            if self.config.has_option('general', 'asset'):
                self.asset = self.config.get('general', 'asset')
            else:
                self.asset = None
        else:
            self.device = None
            self.asset = None

    def updateDevName(self):
        if self.device:
            dev = IOT.getDevice(self.device)
            if dev:
                if 'title' in dev and dev['title']:
                    self.selectedDeviceName = dev['title']
                else:
                    self.selectedDeviceName = dev['name']

    def saveConfig(self):
        if not self.config.has_section('general'):
            self.config.add_section('general')
        self.config.set('general', 'device', self.device)
        self.config.set('general', 'asset', self.asset)
        with open(appConfigFileName, 'w') as f:
            self.config.write(f)

    def showSelectDevice(self, relativeTo):

        dropdown = DropDown()  # auto_width=False, width='140dp'
        devices = IOT.getDevices(data.credentials.groundid)
        for dev in devices:
            btn = Button(size_hint_y=None, height='32dp')
            btn.DeviceId = dev['id']
            if dev['title']:
                btn.text = dev[
                    'title']  # for old devices that didn't ahve a title yet.
            else:
                btn.text = dev['name']
            btn.bind(on_release=lambda btn: self.selectDevice(
                btn.parent.parent, btn.DeviceId, btn.text))
            dropdown.add_widget(btn)
        dropdown.open(relativeTo)

    def selectDevice(self, dropdown, deviceId, title):
        if dropdown:
            dropdown.dismiss()
        self.selectedDeviceName = title
        self.device = deviceId
        if self.asset:
            IOT.unsubscribe(self.asset)
        self.asset = None
        if self.device:
            assets = IOT.getAssets(self.device)
            locationAsset = [
                asset for asset in assets
                if str(asset['name']).startswith('prediction_distance_json')
            ]
            if locationAsset and len(locationAsset) > 0:
                self.asset = str(locationAsset[0]['id'])
                IOT.subscribe(self.asset, self.destinationChanged)
        if self.isRunning and platform == 'android':
            osc.sendMsg('/device', [str(self.device)], port=IPCServicePort)
        self.saveConfig()

    def destinationChanged(self, value):
        if value:
            self.destination = str(value)
        else:
            self.destination = 'Unknown'

    def startService(self, level):
        self.isRunning = True
        if platform == 'android':
            if not self.service:
                self.service = AndroidService('my gps service', 'running')
            if self.device:
                self.service.start(level + '|' + self.device + '|' +
                                   data.credentials.deviceAuth + '|' +
                                   IOT._brokerPwd)
            else:
                self.service.start(level)

    def stopService(self):
        if self.isRunning:
            if self.service:
                osc.sendMsg('/stop', [''], port=IPCServicePort)
                try:
                    self.service.stop()
                    self.currentstatus = "GPS stopped"
                except Exception as e:
                    logging.exception('failed to stop service')
                    self.currentstatus = "failed to stop service: " + e.message

        self.isRunning = False

    def on_update_from_service(self, message, *args):
        self.currentstatus = message[2]
Beispiel #12
0
class Service():
    #Configuracoes do ThreadComm
    CONFIG_THREADCOMMPORT = 51352
    CONFIG_THREADCOMMID = "sigmawebplus"
    
    #Variaveis
    _state = STATE_NOTSTARTED
    _formerState = STATE_NOTSTARTED
    _forceThread = None
    _androidTrigger = False #Hack: O service do Android soh pode ser aberto pelo main thread. Uso essa flag para avisar o main thread a hora de abrir
    _androidTriggerEnd = False
    _androidService = None #Guarda do ponteiro do Android Service, para poder fechar depois
    _lastDisconnection = 0 #Essa variavel serve para ter um timeout de 5 segundos entre cada reconexao
    
    #Objetos
    _threadComm = None #Ponteiro para o objeto do ThreadComm (utilizado para se comunicar com o service)
    _data = None       #Objeto 'Dict' utilizado para armazenar todos as propriedade que estão sinronizadas com o service
    
    '''
    Salva os dados recebido como parametro e inicializa o servico de forma assincrona
    Nota: Se o service já existir, os dados serão sobreescritos em favor dos dados do service
    '''
    def start(self, data, forceThread=False):
        if (self.getState() == STATE_NOTSTARTED):
            Debug().note('service.start(): Iniciando server')
            self._setState(STATE_CONNECTING)
            self._data = data #Salva dados no objeto
            self._forceThread = forceThread
            thread = Thread(target=self._start, name='service._start()') #Faz a inicializacao do Service em outro thread
            thread.daemon = False
            thread.start()
        else:
            Debug().note('service.start(): Reiniciando server')
            thread = Thread(target=self._restart, name='service._restart()', args=(data, forceThread))
            thread.daemon = False
            thread.start()
    
    '''
    Manda um aviso para o service se finalizar e espera a resposta do service!
    ATENCAO: Essa funcao eh bloqueante. Ela trava o andamento do programa ateh receber o sinal do service!
    '''
    def stop(self, killService=True):
        while (self.getState() == STATE_CONNECTING): sleep(0.1) #Espera o ThreadComm conectar, caso ele esteja no modo 'Conectando'
        if self.isAlive():
            self._setState(STATE_DISCONNECTING)
            self._stop(killService)
        else:
            Debug().warn('service.stop(): Service nao esta rodando. Nada para parar! CurrentState: '+str(self.getState()))
            
    
    '''
    Retorna True se o service esta conectado e pronto para funcionar
    '''
    def isAlive(self):
        if (self.getState() == STATE_CONNECTEDTHREAD) or (self.getState() == STATE_CONNECTEDANDROID) or (self.getState() == STATE_CONNECTEDREMOTE):
            return True
        else: return False
    
    '''
    Retorna o estado que o objeto se encontra. Uma lista de estados pode ser vista no inicio desse arquivo
    '''
    def getState(self):
        return self._state
    
    def getFormerState(self):
        return self._formerState
    
    '''
    Retorna o valor da chave solicitada
    '''
    def getKey(self, key):
        try: return str(self._data[key])
        except: return ''
    
    '''
    Seta o valor da chave e avisa o service desta mudanca
    '''
    def setKey(self, key, value):
        self._data[key] = str(value)
        if self.isAlive(): self._sendKey(key)
    
    '''
    Este metodo faz o objeto buscar se há novas mensagens no ThreadComm
    Retorna uma lista com as keys e valores de todas os dados modificados [[key1, value1], [key2, value2], ...]
    Nota: Ele não vai retornar a key se o valor recebido for igual o valor já presente!
    Nota2: Ele tambem é responsavel pelo main loop do service (ele responde outros tipos de mensagens)
    Nota3: A logica do loop foi movida para a funcao _parseMessage() para melhorar a leitura
    '''
    def getKeys(self):
        self._startAndroid() #Hack: O service do Android soh pode ser aberto pelo main thread. Uso essa funcao para o main thread verificar se deve abrir ou nao
        if not self.isAlive(): return None #Verifica se o servidor esta conctado
        
        returnData = []
        while True:
            #Busca novas mensagens no ThreadCom
            try: message = self._threadComm.recvMsg()
            except: break
            
            #Faz o parse da mensagem recebida e, se o valor retornado não for nulo, adiciona na returnData
            data = self._parseMessage(message)
            if data is not None: returnData.append(data)
        
        return returnData
    
    '''
    ''   PRIVATE METHODS
    '''
    
    def __init__(self):
        self._data = {}
    
    def _setState(self, value):
        self._formerState = self._state
        self._state = value
    
    def _restart(self, data, forceThread=False):
        Debug().note('service._restart()')
        self.stop()
        self.start(data, forceThread)
    
    '''
    Metodo interno para iniciar o service. Ele primeiro vai verificar se o service já não está rodando
    Se o service já estiver rodando, ele salva o ponteiro do ThreadComm e solicita ao service todas os seus dados
    Se o service não estiver rodando, ele chama o metodo _startService() para inicializar o service 
    '''
    def _start(self):
        Debug().note('service._start()')
        
        while not (self._lastDisconnection+1 < time()):
            sleep(0.1)
        
        self._threadComm = ThreadComm(self.CONFIG_THREADCOMMPORT, self.CONFIG_THREADCOMMID, ThreadCommClient)
        try: self._threadComm.start()
        except ThreadCommException as e: #Servico nao esta rodando
            Debug().note('service._start(): Service nao esta aberto')
            self._startService()
        else: #Servico já esta rodando
            Debug().note('service._start(): Service ja esta aberto')
            self._threadComm.sendMsg("AKEY") #Solicita todas as keys que o server tem disponivel!
            if (self._forceThread == False) or (platform != 'android'): self._setState(STATE_CONNECTEDREMOTE)
            else:
                Debug().warn('service._start(): Finalizando service e abrindo denovo para atender a forceThread')
                currentData = self._data
                self._stop()
                self.start(currentData, True)
    
    '''
    Metodo que inicializa o service de acordo com a plataforma
    Ele inicializa o service e depois conecta o ThreadComm com o service
    '''
    def _startService(self):
        if (platform == 'android') and (not self._forceThread): connectThread = False
        else: connectThread = True
        
        if not connectThread:
            Debug().note('service._startService(): Esperando o _androidTrigger')
            self._androidTrigger = True #Hack: Ativa a flag para abrir o service do android. O android soh deixa o service ser aberto pelo main thread
            while (self._androidTrigger == True): pass #Espera o service abrir
        else:
            from main import MainService
            mainService = MainService()
            thread = Thread(target=mainService.run)
            thread.daemon = False
            thread.name = "MainService"
            thread.start()
            
        Debug().note('service._startService(): Esperando o ThreadComm conectar')
        while True: #Todo: Colocar um timeout
            try: self._threadComm.start()
            except ThreadCommException: pass
            else: break
        
        Debug().note('service._startService(): Enviando todos os dados')
        for key in self._data:
            self._sendKey(key)
        self._threadComm.sendMsg("STRT") #Sinal para o Service iniciar
        
        #Aguarda a resposta do service
        Debug().note('service._startService(): Aguardando o service ser iniciado')
        message = None
        while message != 'STRT':
            try: message = self._threadComm.recvMsg()
            except: pass
        
        if connectThread: self._setState(STATE_CONNECTEDTHREAD)
        else: self._setState(STATE_CONNECTEDANDROID)
    
    '''
    Metodo utilizado para fazer um parse da mensagem recebida e reagir conforme
    Retorna: Uma lista [key, value] se a mensagem for do tipo "SKEY" e o valor recebido for diferente do que já está na self._data
    '''
    def _parseMessage(self, message):
        if message[:4] == "SKEY": #Set key
            #Extrai dados da mensagem
            length = int(message[4:6]) 
            key, value = [message[6:6+length], message[6+length:]]
            
            '''
            Se o valor for diferente do que está salvo:
                * Salva o novo valor
                * Retorna o nome da chave e seu respectivo valor
            '''
            if value <> self.getKey(key):
                self._data[key] = value
                return key, value
        elif message[:4] == "GKEY": #Get key
            key = message[4:]  #Extrai o nome da key na mensagem
            self._sendKey(key) #Manda o valor da key de volta para o service
        elif message[:4] == "AKEY": #Get all keys
            for key in self.data:
                self._sendKey(key)
        elif message[:4] == "NOTI": #Send a notification
            notificationMsg = message[4:].split("|")
            notificationObject = Notification(*notificationMsg)
            notificationObject.enableActivity = True #O notification normalmente funciona no Service, isso serve para mudar o modo para Activity
            notificationObject.notify()
        elif message[:4] == "STOP": #O Service foi finalizado de forma inesperada
            self._stop(False, True)
            Debug().error('Service finalizado de forma inesperada. O applicativo esta sendo fechado de forma forcada')
            return ['app_delete', '1']
    
    '''
    Metodo privado que envia para o service a KEY especificada, no formato especificado
    Voce nao precisa informar o valor, ele pega direto do self._data
    '''
    def _sendKey(self, key):
        length = str(len(key)).zfill(2)
        self._threadComm.sendMsg("SKEY"+length+key+self.getKey(key))
    
    '''
    O service do Android soh pode ser aberto pelo main thread. 
    Essa funcao verifica uma flag de aberura. Caso ela esteja ligada, ele abre o Service e desliga a flag
    '''
    def _startAndroid(self):
        if self._androidTrigger:
            Debug().note('service._startAndroid(): Iniciando o service no Android')
            from android import AndroidService
            self._androidService = AndroidService('SigmaWeb+', 'Monitorando') 
            self._androidService.start()
            self._androidTrigger = False
        
        if self._androidTriggerEnd:
            Debug().note('service._startAndroid(): Finalizando o service no Android')
            if self._androidService is not None:
                self._androidService.stop()
            else:
                Debug().warn('service._startAndroid(): Service nao pode ser finalizado. Nao esta aberto')
            self._androidService = None
            self._androidTriggerEnd = False
    
    '''
    Para o service do android caso ele esteja iniciado
    '''
    def _stopAndroid(self):
        Debug().note('service._stopAndroid()')
        if (platform == 'android') and (self.getFormerState() == STATE_CONNECTEDREMOTE):
            from android import AndroidService
            self._androidService = AndroidService('SigmaWeb+', 'Monitorando')
        
        if (self._androidService != None):
            Debug().note('service._stopAndroid(): Esperando o _androidTriggerEnd') 
            self._androidTriggerEnd = True
            if currentThread().name == 'service._restart()':
                while self._androidTriggerEnd: sleep(0.1)
            else:
                self._startAndroid()
    
    '''
    Funcao privada para parar o service (ela nao faz checks se o service foi iniciado. Isso eh trabalho da funcao publica)
    '''
    def _stop(self, killService=True, forceKillAndroid=False):
        if killService: 
            self._threadComm.sendMsg("KILL") #Manda o sinal para o service terminar
            
            '''
            A maneira que esta funcao verifica se o service foi desconectado eh a seguinte:
                1) Espera o service mandar uma mensagem STOP (avisando que está quase sendo desligado)
                2) Flooda o service com mensagens NULL, ateh que elas comecem a retornar erro
            '''
            Debug().note('service.stop(): Aguardando o service ser desligado')
            message = None
            while message != 'STOP':
                try: message = self._threadComm.recvMsg()
                except: pass
            while True:
                try: self._threadComm.sendMsg("NULL")
                except: break
                sleep(0.1)
                
        Debug().note('service.stop(): Limpando a memoria')
        #Limpa a memoria e limpa o estado do objeto
        self._threadComm.stop()
        if killService or forceKillAndroid: self._stopAndroid()
        self._data = None
        self._threadComm = None
        self._setState(STATE_NOTSTARTED)
        self._lastDisconnection = time()
        
Beispiel #13
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)

    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 = False
            self.ids.run_plugin = 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

        first = True
        for name in self.plugins_list:
            widget = LabeledCheckBox(text=name, group="app")
            if first:
                widget.active = True
                self.ids.checkbox_app.selected = name
                first = False
            widget.bind(on_active=self.on_checkbox_app_active)
            self.ids.checkbox_app_layout.add_widget(widget)
        self.ids.checkbox_app_layout.height = len(self.plugins_list) * 230

        # 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)
        except Exception as e:
            pass

    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}\";"

        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:
                    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 0755 " + 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 on_checkbox_app_active(self, obj):
        for cb in self.ids.checkbox_app_layout.children:
            if cb is not obj:
                cb.active = False

        for cb in self.ids.checkbox_app_layout.children:
            if cb.active:
                self.ids.checkbox_app.selected = cb.text

        # Yuanjie: try to load readme.txt
        if self.service:
            return True

        app_path = self.plugins_list[self.ids.checkbox_app.selected][0]
        if os.path.exists(os.path.join(app_path, "readme.txt")):
            with open(os.path.join(app_path, "readme.txt"), 'r') as ff:
                self.error_log = self.ids.checkbox_app.selected + ": " + ff.read(
                )
        else:
            self.error_log = self.ids.checkbox_app.selected + ": no descriptions."

        return True

    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 start_service(self, app_name):
        if platform == "android" and app_name in self.plugins_list:
            if self.service:
                # stop the running service
                self.stop_service()

            # Show logs on screen

            # 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)
            self.service.start(app_name + ":" +
                               self.plugins_list[app_name][0])  # app name
            self.default_app_name = app_name

        else:
            self.error_log = "Error: " + app_name + "cannot be launched!"

    def stop_service(self):
        if self.service:
            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

            # Haotian: save orphan log
            dated_files = []
            self.__logdir = main_utils.get_mobileinsight_log_path()
            self.__phone_info = main_utils.get_phone_info()
            mi2log_folder = os.path.join(main_utils.get_cache_dir(), "mi2log")
            for subdir, dirs, files in os.walk(mi2log_folder):
                for f in files:
                    fn = os.path.join(subdir, f)
                    dated_files.append((os.path.getmtime(fn), fn))
            dated_files.sort()
            dated_files.reverse()
            if len(dated_files) > 0:
                self.__original_filename = dated_files[0][1]
                # print "The last orphan log file: " +
                # str(self.__original_filename)
                chmodcmd = "chmod 644 " + self.__original_filename
                p = subprocess.Popen("su ",
                                     executable=main_utils.ANDROID_SHELL,
                                     shell=True,
                                     stdin=subprocess.PIPE,
                                     stdout=subprocess.PIPE)
                p.communicate(chmodcmd + '\n')
                p.wait()
                self._save_log()

    def _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\n' +
                      'Copyright (c) 2014 – 2017')
        popup = Popup(title='About MobileInsight',
                      content=Label(text=about_text),
                      size_hint=(.8, .4))
        popup.open()
class SettingsFrame(StackLayout):
    """Settingsframe is the main frame of the application"""
    cfg_file = None
    """The config file to use"""
    service_status = None
    """The status of the service"""
    service_progress = None
    """The progress of the current job"""

    def init(self, _cfg_file=None):
        self.ids.destination_host.ids.input_selection.bind(text=self._update_host)
        self.ids.destination_path.on_status = self.do_on_smbselector_status
        self.load_settings(_cfg_file)
        self.service = None
        osc.init()
        self.oscid = osc.listen(port=3002)
        osc.bind(self.oscid, self.progress_callback, "/progress_callback")
        osc.bind(self.oscid, self.status_callback, "/status_callback")

        # Check if service is running
        self.service_running = False
        osc.sendMsg("/status", [], port=3000)
        osc.sendMsg("/progress", [], port=3000)
        sleep(0.3)
        osc.readQueue(self.oscid)


        Clock.schedule_interval(self.process_messages, 1)

    ####### Service #################
    #######################################################################################


    def do_on_smbselector_status(self, _message):
        """
        :param _message: A string message
        """
        self.ids.l_test_smbselector_result.text = re.sub("(.{40})", "\\1\n", _message, 0, re.DOTALL)
    def process_messages(self, *args):
        """Receive messages"""
        osc.readQueue(self.oscid)

    def status_callback(self, *args):
        """If the client receives a status message, reflect that in the label_status widget
        :param args: Message arguments.
        """
        self.service_running = True
        self.service_status = str(args[0][2])
        self.ids.label_status.text = self.service_status

    def progress_callback(self, *args):
        """If the client receives a progress message, reflect that in the label_progress widget
        :param args: Message arguments.
        """
        self.service_running = True
        self.service_progress = str(args[0][2])
        self.ids.label_progress.text = re.sub("(.{40})", "\\1\n", self.service_progress, 0, re.DOTALL)

    def start_service(self):
        """Start the service"""
        self.save_settings()
        print("Starting service")
        self.service_running = False
        osc.sendMsg("/status", [], port=3000)
        osc.sendMsg("/progress", [], port=3000)
        sleep(0.1)
        osc.readQueue(self.oscid)
        if not self.service_status:
            # Wait a little longer and try again
            sleep(0.5)
            osc.readQueue(self.oscid)

        if not self.service_status:
            print("Start_service: Service is not running, starting")
            if self.service is None:

                if platform == "android":
                    from android import AndroidService
                    self.service = AndroidService("Optimal file sync service", "running")
                    self.service.start("service started")
                else:
                    # Start process on linux.
                    print("Running on !android initializing service using Popen.")
                    self.service = subprocess.Popen(args = ["python", "./service/main.py"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        else:
            print("Start_service: Service is already running, not starting.")


    def stop_service(self):
        """Stop the service"""
        print("Asking service to stop.")
        self.service_running = False

        osc.sendMsg("/status", [], port=3000)
        sleep(0.2)
        osc.readQueue(self.oscid)

        osc.sendMsg("/stop", [], port=3000)
        sleep(0.2)
        osc.readQueue(self.oscid)
        if self.service is not None and platform == "android":
            self.service.stop()
            self.service = None


    ####### GUI #################
    #######################################################################################

    def _update_host(self, *args):
        """If the host selection is changed, set the host."""
        self.ids.destination_path.host = self.ids.destination_host.ids.input_selection.text

    def reload_settings(self):
        """Reload settings from current settings file"""
        self.load_settings(self.cfg_file)

    def load_settings(self, _cfg_file=None):
        """
        Load settings from a settings file
        :param _cfg_file: A file with settings
        """
        self.cfg_file = _cfg_file
        cfg = ConfigParser.SafeConfigParser()
        cfg.read(_cfg_file)

        self.ids.sourcedir_select.selection = cfg.get("Job_Default", "source_folder")
        self.ids.destination_host.selection = cfg.get("Job_Default", "destination_hostname")
        self.ids.destination_path.selection = cfg.get("Job_Default", "destination_folder")
        self.ids.destination_username.text = cfg.get("Job_Default", "destination_username")
        self.ids.destination_password.text = cfg.get("Job_Default", "destination_password")

    def save_settings(self):
        """Save settings to file"""
        cfg = ConfigParser.SafeConfigParser()
        cfg.read(self.cfg_file)

        cfg.set("Job_Default", "source_folder", self.ids.sourcedir_select.selection)
        cfg.set("Job_Default", "destination_hostname", self.ids.destination_host.selection)
        cfg.set("Job_Default", "destination_folder", self.ids.destination_path.selection)
        cfg.set("Job_Default", "destination_username", self.ids.destination_username.text)
        cfg.set("Job_Default", "destination_password", self.ids.destination_password.text)
        f = open(self.cfg_file, "wb")
        cfg.write(f)
        f.close()

    def test_connection(self):
        """Test SMB connection by connecting to a server"""
        try:
            self.ids.l_test_connection_result.text = "Testing..."
            _smb = smb_connect(_hostname=self.ids.destination_host.selection,
                               _username=self.ids.destination_username.text,
                               _password=self.ids.destination_password.text )
            self.ids.l_test_connection_result.text = "Connection successful!"
        except Exception as e:
            self.ids.l_test_connection_result.text = "Test failed, error connecting: " + str(e)

        try:
            _shares = _smb.listShares()
            self.ids.l_test_connection_result.text = "Listing shares (" + str(len(_shares)) + ") successful!"
        except Exception as e:
            self.ids.l_test_connection_result.text = "Test failed, error listing shares: " + str(e)
Beispiel #15
0
class OSCClient():
    def __init__(self, app):
        self.subprocess = None
        self.app = app
        self.mainscreen = app.get_running_app().manager.get_screen(
            'main_screen')
        self.answers_count = '0'
        self.osc = osc
        self.osc.init()
        self.oscid = self.osc.listen(port=3002)
        self.osc.bind(self.oscid, self.pong, '/pong')
        self.osc.bind(self.oscid, self.read_status, '/status')
        self.osc.bind(self.oscid, self.set_answers_count, '/answers count')
        self.osc.bind(self.oscid, self.return_log_from_service, '/log')
        self.osc.bind(self.oscid, self.on_first_auth, '/first auth')
        self.osc.bind(self.oscid, self.on_auth_success, '/auth successful')
        self.osc.bind(
            self.oscid, self.on_auth_twofactor, '/auth twofactor needed'
        )
        self.osc.bind(self.oscid, self.on_auth_captcha, '/auth captcha needed')
        self.osc.bind(self.oscid, self.on_auth_fail, '/auth failed')

        self.osc_read_event = None
        self.answers_request_event = None
        self.start_reading_osc_queue()
        self.ping()

    def start_requesting_answers_count(self):
        if not self.answers_request_event:
            self.answers_request_event = Clock.schedule_interval(
                lambda *x:
                    osc.sendMsg('/request answers count', [], port=3000),
                5
            )

    def stop_requesting_answers_count(self):
        if self.answers_request_event:
            self.answers_request_event.cancel()
            self.answers_request_event = None

    def start_reading_osc_queue(self):
        if not self.osc_read_event:
            self.osc_read_event = Clock.schedule_interval(
                lambda *x: self.osc.readQueue(self.oscid),
                0.1
            )

    def stop_reading_osc_queue(self):
        if self.osc_read_event:
            self.osc_read_event.cancel()
            self.osc_read_event = None

    def start(self):
        self.logging_function(u'Начинаю запуск бота', 1, time.time())
        self.start_reading_osc_queue()

        if platform == 'android':
            # self.subprocess = autoclass(
            #     'org.fogaprod.vkbot.dev.ServiceBotservice')
            # mActivity = autoclass(
            #     'org.kivy.android.PythonActivity').mActivity
            # argument = ''
            # self.subprocess.start(mActivity, argument)
            self.subprocess = AndroidService('VKBot', 'Бот работает')
            self.subprocess.start('Сервис запущен')
        else:
            self.subprocess = subprocess.Popen(
                ['python2.7', 'service/main.py'])

        self.start_requesting_answers_count()

    def stop(self):
        self.stop_requesting_answers_count()

        if platform == 'android':
            if self.subprocess:
                # self.subprocess = autoclass(
                #     'org.fogaprod.vkbot.dev.ServiceBotservice')
                # mActivity = autoclass(
                #     'org.kivy.android.PythonActivity').mActivity
                # argument = ''
                # self.subprocess.stop(mActivity)
                self.subprocess.stop()
        else:
            osc.sendMsg('/exit', [], port=3000)

            if self.subprocess is not None:
                self.subprocess.kill()

        self.stop_reading_osc_queue()
        self.logging_function(
            u'[b]Бот полностью остановлен[/b]', 2, time.time())

    def ping(self):
        self.logging_function(u'Проверяю, запущен ли бот...', 1)
        self.osc.sendMsg('/ping', [], port=3000)

    def pong(self, message, *args):
        self.logging_function(
            u'[b]Бот уже запущен! Переподключение завершено[/b]',
            2, time.time()
        )
        self.subprocess = AndroidService('VKBot', 'Бот работает')
        self.start_requesting_answers_count()
        self.mainscreen.ids.main_btn.text = self.mainscreen.stop_bot_text

    def read_status(self, message, *args):
        status = message[2]

        if status == 'launched':
            self.logging_function(u'[b]Бот запущен[/b]', 2, time.time())
            self.mainscreen.ids.main_btn.text = self.mainscreen.stop_bot_text

        elif status == 'exiting':
            self.stop()
            self.mainscreen.ids.main_btn.text = self.mainscreen.launch_bot_text

        elif status == 'settings changed':
            self.app.close_settings()
            self.app.destroy_settings()
            self.app.load_config()

    def set_answers_count(self, message, *args):
        self.answers_count = str(message[2])
        if self.mainscreen:
            self.mainscreen.update_answers_count(self.answers_count)

    def return_log_from_service(self, message, *args):
        self.logging_function(*literal_eval(message[2]))

    def logging_function(self, message, log_importance, t=None):
        if time is None:
            t = time.time()
        self.mainscreen.put_log_to_queue(message, log_importance, t)

    def on_first_auth(self, message, *args):
        self.logging_function(
            u'[b]Пожалуйста, авторизируйтесь для начала работы[/b]',
            2, time.time()
        )
        self.app.open_auth_popup()

    def send_auth_request(self, login, password):
        self.logging_function(u'[b]Начинаю авторизацию[/b]', 2)
        self.osc.sendMsg(
            '/auth request',
            [str((login.encode('utf8'), password.encode('utf8')))],
            port=3000
        )

    def on_auth_success(self, message, *args):
        self.logging_function(
            u'[b][color=#33ff33]Авторизация удалась. '
            u'Вы [i]превосходны[/i]![/color][/b]',
            2
        )
        self.app._cached_password = None

    def on_auth_twofactor(self, message, *args):
        self.logging_function(
            u'[b]Необходимо ввести код для двухфакторной авторизации в '
            u'появившемся окне[/b]', 2, time.time()
        )
        self.app.open_twofa_popup()
        self.logging_function(u'Жду кода...', 1)

    def send_twofactor_code(self, code):
        self.osc.sendMsg('/twofactor response', [str(code), ], port=3000)
        self.logging_function(u'Код отправлен', 0)

    def on_auth_captcha(self, message, *args):
        self.logging_function(
            u'[b]Пожалуйста, решите капчу[/b]', 2, time.time())
        self.app.open_captcha_popup(message[2])
        self.logging_function(u'Жду кода...', 1)

    def send_captcha_code(self, code):
        self.osc.sendMsg(
            '/captcha response', [str(code.encode('utf8')), ], port=3000)
        self.logging_function(u'Код отправлен', 0)

    def on_auth_fail(self, message, *args):
        self.logging_function(
            u'[b][color=#ff3300]Авторизация не удалась![/color][/b]', 2)