Exemplo n.º 1
0
    def send(self, device):
        if self.view is not None:
            from device_state import DeviceState
            width = DeviceState.get_view_width(view_dict=self.view)
            height = DeviceState.get_view_height(view_dict=self.view)
        else:
            width = device.get_width()
            height = device.get_height()

        x, y = UIEvent.get_xy(x=self.x, y=self.y, view=self.view)
        if not x or not y:
            # If no view and no coordinate specified, use the screen center coordinate
            x = width / 2
            y = height / 2

        start_x, start_y = x, y
        end_x, end_y = x, y
        duration = 500

        if self.direction == "UP":
            start_y -= height * 2 / 5
            end_y += height * 2 / 5
        elif self.direction == "DOWN":
            start_y += height * 2 / 5
            end_y -= height * 2 / 5
        elif self.direction == "LEFT":
            start_x -= width * 2 / 5
            end_x += width * 2 / 5
        elif self.direction == "RIGHT":
            start_x += width * 2 / 5
            end_x -= width * 2 / 5

        device.view_drag((start_x, start_y), (end_x, end_y), duration)
        return True
Exemplo n.º 2
0
 def get_xy(x, y, view):
     if x and y:
         return x, y
     if view:
         from device_state import DeviceState
         return DeviceState.get_view_center(view_dict=view)
     return x, y
Exemplo n.º 3
0
 def get_current_state(self):
     self.logger.debug("getting current device state...")
     current_state = None
     try:
         views = self.get_views()
         foreground_activity = self.get_top_activity_name()
         activity_stack = self.get_current_activity_stack()
         background_services = self.get_service_names()
         screenshot_path = self.take_screenshot()
         self.logger.debug("finish getting current device state...")
         from device_state import DeviceState
         current_state = DeviceState(
             self,
             views=views,
             foreground_activity=foreground_activity,
             activity_stack=activity_stack,
             background_services=background_services,
             screenshot_path=screenshot_path)
     except Exception as e:
         self.logger.warning("exception in get_current_state: %s" % e)
         import traceback
         traceback.print_exc()
     self.logger.debug("finish getting current device state...")
     self.last_know_state = current_state
     if not current_state:
         self.logger.warning("Failed to get current state!")
     return current_state
Exemplo n.º 4
0
    def generate_event_based_on_utg(self):
        """
        generate an event based on current device state
        note: ensure these fields are properly maintained in each transaction:
          last_event_flag, last_touched_view, last_state, exploited_views, state_transitions
        @return: AppEvent
        """
        self.save_state_transition(self.last_event_str, self.last_state,
                                   self.current_state)

        if self.device.is_foreground(self.app):
            # the app is in foreground, clear last_event_flag
            self.last_event_flag = EVENT_FLAG_STARTED
        else:
            number_of_starts = self.last_event_flag.count(EVENT_FLAG_START_APP)
            # If we have tried too many times but the app is still not started, stop DroidBot
            if number_of_starts > START_RETRY_THRESHOLD:
                raise InputInterruptedException("The app cannot be started.")

            # if app is not started, try start it
            if self.last_event_flag.endswith(EVENT_FLAG_START_APP):
                # It seems the app stuck at some state, and cannot be started
                # just pass to let viewclient deal with this case
                pass
            else:
                start_app_intent = self.app.get_start_intent()

                self.last_event_flag += EVENT_FLAG_START_APP
                self.last_event_str = EVENT_FLAG_START_APP
                return IntentEvent(start_app_intent)

        # select a view to click
        view_to_touch = self.select_a_view(self.current_state)

        # if no view can be selected, restart the app
        if view_to_touch is None:
            stop_app_intent = self.app.get_stop_intent()
            self.last_event_flag += EVENT_FLAG_STOP_APP
            self.last_event_str = EVENT_FLAG_STOP_APP
            return IntentEvent(stop_app_intent)

        view_to_touch_str = view_to_touch['view_str']
        if view_to_touch_str.startswith('BACK'):
            result = KeyEvent('BACK')
        else:
            x, y = DeviceState.get_view_center(view_to_touch)
            result = TouchEvent(x, y)

        self.last_event_flag += EVENT_FLAG_TOUCH
        self.last_event_str = view_to_touch_str
        self.save_explored_view(self.last_state, self.last_event_str)
        return result
 def get_transformed_event(self, device):
     event_dict = self.event_dict.copy()
     if 'target_view' in event_dict:
         target_view = event_dict.pop('target_view')
         target_view_selector = event_dict.pop('target_view_selector')
         state = device.get_current_state()
         matched_view = None
         for view_dict in state.views:
             if target_view_selector.match(view_dict):
                 matched_view = view_dict
                 break
         if matched_view is None:
             device.logger.warning("target_view no match: %s" % target_view)
         else:
             from device_state import DeviceState
             (event_dict['x'],
              event_dict['y']) = DeviceState.get_view_center(matched_view)
     return AppEvent.get_event(event_dict)
Exemplo n.º 6
0
    def select_a_view(self, state):
        """
        select a view in the view list of given state, let droidbot touch it
        @param state: DeviceState
        @return:
        """
        views = []
        for view in state.views:
            if view['enabled'] and len(
                    view['children']
            ) == 0 and DeviceState.get_view_size(view) != 0:
                views.append(view)

        if not self.no_shuffle:
            random.shuffle(views)

        # add a "BACK" view, consider go back last
        mock_view_back = {
            'view_str': 'BACK_%s' % state.foreground_activity,
            'text': 'BACK_%s' % state.foreground_activity
        }
        views.append(mock_view_back)

        # first try to find a preferable view
        for view in views:
            view_text = view['text'] if view['text'] is not None else ''
            view_text = view_text.lower().strip()
            if view_text in self.preferred_buttons and \
                            (state.foreground_activity, view['view_str']) not in self.explored_views:
                self.device.logger.info("selected an preferred view: %s" %
                                        view['view_str'])
                return view

        # try to find a un-clicked view
        for view in views:
            if (state.foreground_activity,
                    view['view_str']) not in self.explored_views:
                self.device.logger.info("selected an un-clicked view: %s" %
                                        view['view_str'])
                return view

        # if all enabled views have been clicked, try jump to another activity by clicking one of state transitions
        if not self.no_shuffle:
            random.shuffle(views)
        transition_views = {
            transition[0]
            for transition in self.state_transitions
        }
        for view in views:
            if view['view_str'] in transition_views:
                self.device.logger.info("selected a transition view: %s" %
                                        view['view_str'])
                return view

        # no window transition found, just return a random view
        # view = views[0]
        # self.device.logger.info("selected a random view: %s" % view['view_str'])
        # return view

        # DroidBot stuck on current state, return None
        self.device.logger.info("no view could be selected in state: %s" %
                                state.tag)
        return None