Skip to content

Commit

Permalink
implement event factory
Browse files Browse the repository at this point in the history
  • Loading branch information
yuanchun-li committed Jun 25, 2015
1 parent df69d7a commit 8b3c4ce
Show file tree
Hide file tree
Showing 4 changed files with 189 additions and 127 deletions.
77 changes: 74 additions & 3 deletions droidbot/app_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@

import logging
import json
import random
import time
import threading

from types import Device, App, Intent

ENV_POLICIES = [
"none",
Expand All @@ -18,6 +23,10 @@
]


class UnknownEnvException(Exception):
pass


class AppEnv(object):
"""
This class describes a environment attribute of device
Expand All @@ -31,6 +40,13 @@ def to_json(self):
def __str__(self):
return self.to_dict().__str__()

def deploy(self, device):
"""
deploy this env to device
:param device: Device
"""
raise NotImplementedError


class StaticAppEnv(AppEnv):
"""
Expand All @@ -57,6 +73,23 @@ def __init__(self, name='Lynn', phone="1234567890", email="droidbot@honeynet.com
self.email = email
self.env_type = 'contact'

def deploy(self, device):
"""
add a contact to the device
"""
assert device.get_adb() is not None
extra_string = self.__dict__
extra_string.pop('env_type')
contact_intent = Intent(prefix="start",
action="android.intent.action.INSERT",
mime_type="vnd.android.cursor.dir/contact",
extra_string=extra_string)
device.send_intent(intent=contact_intent)
time.sleep(2)
device.get_adb().press("BACK")
time.sleep(2)
device.get_adb().press("BACK")


class SettingsAppEnv(StaticAppEnv):
"""
Expand All @@ -68,6 +101,9 @@ def __init__(self, table_name="system", name="screen_brightness", value="50"):
self.value = value
self.env_type = 'settings'

def deploy(self, device):
device.change_settings(self.table_name, self.name, self.value)


class CallLogEnv(StaticAppEnv):
"""
Expand All @@ -85,6 +121,32 @@ def __init__(self, phone="1234567890", call_in=True, accepted=True):
self.accepted = accepted
self.env_type = 'calllog'

def deploy(self, device):
if self.call_in:
self.deploy_call_in(device)
else:
self.deploy_call_out(device)

def deploy_call_in(self, device):
"""
deploy call in log event to device
"""
if not device.receive_call(self.phone):
return
time.sleep(1)
if self.accepted:
device.accept_call(self.phone)
time.sleep(1)
device.cancel_call(self.phone)

def deploy_call_out(self, device):
"""
deploy call out log event to device
"""
device.call(self.phone)
time.sleep(2)
device.cancel_call(self.phone)


class SMSLogEnv(StaticAppEnv):
"""
Expand All @@ -102,6 +164,12 @@ def __init__(self, phone="1234567890", sms_in=True, content="Hello world"):
self.content = content
self.env_type = 'smslog'

def deploy(self, device):
if self.sms_in:
device.receive_sms(self.phone, self.content)
else:
device.send_sms(self.phone, self.content)


class GPSAppEnv(DynamicAppEnv):
"""
Expand All @@ -114,6 +182,9 @@ def __init__(self, center_x=50, center_y=50, delta_x=1, delta_y=1):
self.delta_y = delta_y
self.env_type = 'gps'

def deploy(self, device):
device.set_continuous_gps(self.center_x, self.center_y, self.delta_x, self.delta_y)


class AppEnvManager(object):
"""
Expand All @@ -135,7 +206,7 @@ def __init__(self, device, app, env_policy):
self.envs = []

if not self.policy or self == None:
self.policy = "dummy"
self.policy = "none"

if self.policy == "none":
self.env_factory = None
Expand All @@ -160,14 +231,14 @@ def deploy(self):
:param device:
:return:
"""
self.logger.info("deploying environment, policy is %s" % self.policy)
self.logger.info("start deploying environment, policy is %s" % self.policy)
if self.env_factory != None:
self.envs = self.generateFromFactory(self.env_factory)
if self.envs is None:
return
for env in self.envs:
self.device.add_env(env)
return
self.logger.info("finish deploying environment, policy is %s" % self.policy)

def dump(self, file):
"""
Expand Down
85 changes: 74 additions & 11 deletions droidbot/app_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,11 @@
android.intent.action.WEB_SEARCH
'''.splitlines()


class UnknownEventException(Exception):
pass


class AppEvent(object):
"""
The base class of all events
Expand All @@ -154,6 +159,14 @@ def to_json(self):
def __str__(self):
return self.to_dict().__str__()

def send(self, device):
"""
send this event to device
:param device: Device
:return:
"""
raise NotImplementedError

@staticmethod
def get_random_instance(device, app):
"""
Expand All @@ -172,16 +185,21 @@ def __init__(self, name):
self.event_type = 'key'
self.name = name

@staticmethod
def get_random_instance(device, app):
key_name = random.choice(POSSIBLE_KEYS)
return KeyEvent(key_name)

def send(self, device):
assert device.get_adb() is not None
device.get_adb().press(self.name)


class UIEvent(AppEvent):
"""
This class describes a UI event of app, such as touch, click, etc
"""

@staticmethod
def get_random_instance(device, app):
if not device.is_foreground(app):
# if current app is in background, bring it to foreground
Expand All @@ -205,11 +223,16 @@ def __init__(self, x, y):
self.x = x
self.y = y

@staticmethod
def get_random_instance(device, app):
x = random.uniform(0, device.get_display_info()['width'])
y = random.uniform(0, device.get_display_info()['height'])
return TouchEvent(x, y)

def send(self, device):
assert device.get_adb() is not None
device.get_adb().touch(self.x, self.y)


class LongTouchEvent(UIEvent):
"""
Expand All @@ -221,11 +244,16 @@ def __init__(self, x, y, duration=2000):
self.y = y
self.duration = duration

@staticmethod
def get_random_instance(device, app):
x = random.uniform(0, device.get_display_info()['width'])
y = random.uniform(0, device.get_display_info()['height'])
return LongTouchEvent(x, y)

def send(self, device):
assert device.get_adb() is not None
device.get_adb().longTouch(self.x, self.y, self.duration)


class DragEvent(UIEvent):
"""
Expand All @@ -239,13 +267,19 @@ def __init__(self, start_x, start_y, end_x, end_y, duration=1000):
self.end_y = end_y
self.duration = duration

@staticmethod
def get_random_instance(device, app):
start_x = random.uniform(0, device.get_display_info()['width'])
start_y = random.uniform(0, device.get_display_info()['height'])
end_x = random.uniform(0, device.get_display_info()['width'])
end_y = random.uniform(0, device.get_display_info()['height'])
return DragEvent(start_x, start_y, end_x, end_y)

def send(self, device):
assert device.get_adb() is not None
device.get_adb().drag((self.start_x, self.start_y),
(self.end_x, self.end_y),
self.duration)

class IntentEvent(AppEvent):
"""
Expand All @@ -256,11 +290,39 @@ def __init__(self, intent):
self.type = 'intent'
self.intent = intent.get_cmd()

@staticmethod
def get_random_instance(device, app):
action = random.choice(POSSIBLE_ACTIONS)
intent = Intent(action=action)
return IntentEvent(intent)

def send(self, device):
assert device.get_adb() is not None
device.get_adb().shell(self.intent)


class EmulatorEvent(AppEvent):
"""
build-in emulator event, including incoming call and incoming SMS
"""
def __init__(self, event_name, event_data):
"""
:param event_name: name of event
:param event_data: data of event
"""
self.event_name = event_name
self.event_data = event_data

def send(self, device):
assert isinstance(device, Device)
if self.event_data == 'call':
device.receive_call()
time.sleep(2)
device.accept_call()
elif self.event_data == 'sms':
device.send_sms()
else:
raise UnknownEventException

class ContextEvent(AppEvent):
"""
Expand Down Expand Up @@ -308,7 +370,7 @@ def __init__(self, device, app, event_policy, event_count, event_duration=2):
self.count = 100

if not self.policy or self.policy == None:
self.policy = "none"
self.policy = "monkey"

if self.policy == "none":
self.event_factory = None
Expand Down Expand Up @@ -360,14 +422,15 @@ def start(self):
start sending event
"""
self.logger.info("start sending events, policy is %s" % self.policy)
if self.event_factory != None:
if self.event_factory is not None:
self.event_factory.start(self)
else:
monkey_cmd = ["monkey", "--throttle", "1000", "-v"]
if self.app.get_package_name() != None:
monkey_cmd += ["-p", self.app.package_name]
monkey_cmd.append(str(self.count))
monkey_cmd = "monkey %s --throttle 1000 -v %d" % (
("" if self.app.get_package_name() is None else "-p " + (self.app.get_package_name())),
self.count
)
self.device.get_adb().shell(" ".join(monkey_cmd))
self.logger.info("finish sending events, policy is %s" % self.policy)


class EventFactory(object):
Expand Down Expand Up @@ -399,13 +462,13 @@ def generate_event(self):


def weighted_choice(choices):
total = sum(w for c,w in choices)
total = sum(choices[c] for c in choices.keys())
r = random.uniform(0, total)
upto = 0
for c,w in choices:
if upto + w > r:
for c in choices.keys():
if upto + choices[c] > r:
return c
upto += w
upto += choices[c]


class DummyEventFactory(EventFactory):
Expand Down
Loading

0 comments on commit 8b3c4ce

Please sign in to comment.