-
Notifications
You must be signed in to change notification settings - Fork 12
Android backend #56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
jontwo
wants to merge
9
commits into
ten10solutions:master
Choose a base branch
from
jontwo:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Android backend #56
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
2b746ab
pycharm ignores etc.
jontwo 0b5c01d
first commit of android backend
jontwo 7cc7b6f
Merge branch 'master' of https://github.com/thetestpeople/Geist
jontwo fb2ffba
android backend part 2: buttons and swipes
jontwo a58b698
code review changes
jontwo c5880c5
code review changes
jontwo f8d2a58
corrected logger setup
jontwo 2777427
corrected logger setup
jontwo 8af225d
made prereq.py more generic
jontwo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -40,3 +40,10 @@ nosetests.xml | |
|
|
||
| # git | ||
| *.orig | ||
|
|
||
| # pycharm | ||
| .idea* | ||
|
|
||
| # rmv stuff | ||
| geist/data/* | ||
| test_repo/* | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,141 @@ | ||
| from __future__ import division, absolute_import, print_function | ||
|
|
||
| import androidwebui.device_store as device_store | ||
| import androidwebui.actions as actions | ||
| import logging | ||
| import numpy as np | ||
| import struct | ||
| import subprocess | ||
| import zlib | ||
| from ..finders import Location, LocationList | ||
| from ._common import BackendActionBuilder | ||
|
|
||
| logger = logging.getLogger(__name__) | ||
|
|
||
|
|
||
| class _ActionsTransaction(object): | ||
| def __init__(self, backend): | ||
| self._actions_builder = BackendActionBuilder(backend) | ||
|
|
||
| def __enter__(self): | ||
| return self._actions_builder | ||
|
|
||
| def __exit__(self, *args): | ||
| self._actions_builder.execute() | ||
| return False | ||
|
|
||
|
|
||
| class AndroidToNumpyReader(object): | ||
| _HEADER = struct.Struct('III') | ||
|
|
||
| def __init__(self, fb, decompress=False): | ||
| self.h = 0 | ||
| self.w = 0 | ||
| if decompress: | ||
| wbits = zlib.MAX_WBITS | 16 | ||
| self._fb = zlib.decompress(fb, wbits) | ||
| else: | ||
| self._fb = fb | ||
| self._np = self._read_dump() | ||
| self._read_w_h_from_header() | ||
|
|
||
| def _read_dump(self): | ||
| return np.fromstring(self._fb, np.uint8) | ||
|
|
||
| def _read_w_h_from_header(self): | ||
| self.w, self.h = AndroidToNumpyReader._HEADER.unpack_from(self._np)[:2] | ||
| logger.debug('read header, w:%s, h%s' % (self.w, self.h)) | ||
|
|
||
| def get_rect(self): | ||
| return 0, 0, self.w, self.h | ||
|
|
||
| def get_image(self): | ||
| return self._np[12:].reshape((self.h, self.w, 4))[:, :, :3] | ||
|
|
||
|
|
||
| class GeistAndroidBackend(object): | ||
| def __init__(self, **kwargs): | ||
| self.device_id = kwargs.get('device_id', None) | ||
| logger.debug('New android backend with device %s' % self.device_id) | ||
| self._devices = device_store.DevicesStore() | ||
| self._devices.update() | ||
| logger.debug('%d devices found' % len(self._devices.get_all_devices())) | ||
|
|
||
| def get_device(self, device_id=None): | ||
| if device_id: | ||
| device = self._devices.get_by_device_id(device_id) | ||
| elif self.device_id: | ||
| device = self._devices.get_by_device_id(self.device_id) | ||
| else: | ||
| device = self._devices.get_first_device() | ||
| return device if device else None | ||
|
|
||
| def actions_transaction(self): | ||
| return _ActionsTransaction(self) | ||
|
|
||
| def capture_locations(self, device_id=None): | ||
| _stream = self.do_screencap(device_id) | ||
| if not _stream: | ||
| logger.warning('no device found') | ||
| # use stream/buffer when we go back to actions.image | ||
| # _buffer = ''.join(list(_stream)) | ||
| # _image = AndroidToNumpyReader(_buffer, True).get_image() | ||
| _image = AndroidToNumpyReader(_stream, True).get_image() | ||
|
|
||
| h, w = _image.shape[:2] | ||
| return LocationList([Location(0, 0, w, h, image=_image)]) | ||
|
|
||
| def do_screencap(self, device_id=None, quality=1): | ||
| device = self.get_device(device_id) | ||
| if not device: | ||
| return None | ||
| # actions.image returns fbcompressed image, just use raw image for now | ||
| # return actions.image(device, quality) | ||
| process = subprocess.Popen( | ||
| r'adb -s {adb_id} shell "screencap | gzip -1" | sed "s/\r$//"'.format( | ||
| adb_id=device.adb_id | ||
| ), | ||
| shell=True, | ||
| stdout=subprocess.PIPE | ||
| ) | ||
| return process.stdout.read() | ||
|
|
||
| def click(self, px, py, device_id=None): | ||
| device = self.get_device(device_id) | ||
| if not device: | ||
| return None | ||
| return actions.clickimage(device, px, py) | ||
|
|
||
| def swipe(self, json_data, device_id=None, time=None): | ||
| device = self.get_device(device_id) | ||
| if not device: | ||
| return None | ||
| return actions.swipeimage(device, json_data, time) | ||
|
|
||
| def press_button(self, button, device_id=None): | ||
| device = self.get_device(device_id) | ||
| if not device: | ||
| return None | ||
| return actions.button(device, button) | ||
|
|
||
| def getrotation(self, device_id=None): | ||
| device = self.get_device(device_id) | ||
| if not device: | ||
| return None | ||
| return actions.getrotation(device) | ||
|
|
||
| def button_down(self, button_num): | ||
| pass | ||
|
|
||
| def button_up(self, button_num): | ||
| pass | ||
|
|
||
| def move(self, point): | ||
| x, y = point | ||
| self.click(x, y) | ||
|
|
||
| def close(self): | ||
| pass | ||
|
|
||
| def __del__(self): | ||
| self.close() | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| try: | ||
| get_ipython().magic(u'pylab') | ||
| except (NameError,): | ||
| pass | ||
| from geist import ( | ||
| GUI, | ||
| DirectoryRepo, | ||
| ApproxTemplateFinder, | ||
| ExactTemplateFinder, | ||
| TemplateFinderFromRepo, | ||
| ) | ||
| from geist.backends.android import GeistAndroidBackend | ||
| from geist.pyplot import Viewer | ||
|
|
||
| repo = DirectoryRepo('test_repo') | ||
| backend = GeistAndroidBackend() | ||
| gui = GUI(backend) | ||
| V = Viewer(gui, repo) | ||
| S = V.save | ||
| C = V.show_capture | ||
| F = V.show_found | ||
| R = V.show_repo | ||
|
|
||
| top = lambda locations: sorted(locations, key=lambda loc: loc.y)[0] | ||
| bottom = lambda locations: sorted(locations, key=lambda loc: loc.y)[-1] | ||
| left = lambda locations: sorted(locations, key=lambda loc: loc.x)[0] | ||
| right = lambda locations: sorted(locations, key=lambda loc: loc.x)[-1] | ||
|
|
||
| approx_finder = TemplateFinderFromRepo(repo, ApproxTemplateFinder) | ||
| exact_finder = TemplateFinderFromRepo(repo, ExactTemplateFinder) | ||
|
|
||
| left_swipe = [ | ||
| {"startx": 100, "starty": 500, "endx": 700, "endy": 500}, | ||
| ] | ||
| right_swipe = [ | ||
| {"startx": 700, "starty": 500, "endx": 100, "endy": 500}, | ||
| ] |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should look at removing the dependency on androidwebui, as discussed.