-
Notifications
You must be signed in to change notification settings - Fork 361
Fastboot Boot support, Android 9 fix, Fixed PycryptodomeAuthSigner's sign method #152
base: master
Are you sure you want to change the base?
Changes from all commits
b2f9730
236f61d
bc7b879
2378dc8
fc28f55
8e2178b
b2bf672
9689e50
e1db3c2
43ee205
4e29501
72a27fe
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,7 @@ | |
import logging | ||
import os | ||
import struct | ||
from io import BytesIO, StringIO | ||
|
||
from adb import common | ||
from adb import usb_exceptions | ||
|
@@ -99,9 +100,9 @@ def HandleSimpleResponses( | |
info_cb: Optional callback for text sent from the bootloader. | ||
|
||
Returns: | ||
OKAY packet's message. | ||
OKAY packet's message | ||
""" | ||
greateggsgreg marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return self._AcceptResponses(b'OKAY', info_cb, timeout_ms=timeout_ms) | ||
return self._AcceptResponses(b'OKAY', info_cb, timeout_ms=timeout_ms)[0] | ||
|
||
def HandleDataSending(self, source_file, source_len, | ||
info_cb=DEFAULT_MESSAGE_CALLBACK, | ||
|
@@ -123,9 +124,9 @@ def HandleDataSending(self, source_file, source_len, | |
FastbootInvalidResponse: Fastboot responded with an unknown packet type. | ||
|
||
Returns: | ||
OKAY packet's message. | ||
tuple (OKAY packet's message, List of preceding Fastboot Messages) | ||
""" | ||
accepted_size = self._AcceptResponses( | ||
accepted_size, _msgs = self._AcceptResponses( | ||
b'DATA', info_cb, timeout_ms=timeout_ms) | ||
|
||
accepted_size = binascii.unhexlify(accepted_size[:8]) | ||
|
@@ -151,24 +152,33 @@ def _AcceptResponses(self, expected_header, info_cb, timeout_ms=None): | |
FastbootInvalidResponse: Fastboot responded with an unknown packet type. | ||
|
||
Returns: | ||
OKAY packet's message. | ||
tuple (OKAY packet's message, List of preceding Fastboot Messages) | ||
""" | ||
|
||
messages = [] | ||
|
||
while True: | ||
response = self.usb.BulkRead(64, timeout_ms=timeout_ms) | ||
header = bytes(response[:4]) | ||
remaining = bytes(response[4:]) | ||
|
||
if header == b'INFO': | ||
info_cb(FastbootMessage(remaining, header)) | ||
fbm = FastbootMessage(remaining, header) | ||
messages.append(fbm) | ||
info_cb(fbm) | ||
elif header in self.FINAL_HEADERS: | ||
if header != expected_header: | ||
raise FastbootStateMismatch( | ||
'Expected %s, got %s', expected_header, header) | ||
if header == b'OKAY': | ||
info_cb(FastbootMessage(remaining, header)) | ||
return remaining | ||
fbm = FastbootMessage(remaining, header) | ||
messages.append(fbm) | ||
info_cb(fbm) | ||
return remaining, messages | ||
elif header == b'FAIL': | ||
info_cb(FastbootMessage(remaining, header)) | ||
fbm = FastbootMessage(remaining, header) | ||
messages.append(fbm) | ||
info_cb(fbm) | ||
raise FastbootRemoteFailure('FAIL: %s', remaining) | ||
else: | ||
raise FastbootInvalidResponse( | ||
|
@@ -188,6 +198,7 @@ def _HandleProgress(self, total, progress_callback): | |
|
||
def _Write(self, data, length, progress_callback=None): | ||
"""Sends the data to the device, tracking progress with the callback.""" | ||
progress = None | ||
if progress_callback: | ||
progress = self._HandleProgress(length, progress_callback) | ||
next(progress) | ||
|
@@ -310,20 +321,24 @@ def Download(self, source_file, source_len=0, | |
Returns: | ||
Response to a download request, normally nothing. | ||
""" | ||
|
||
if isinstance(source_file, str): | ||
source_file_path = str(source_file) | ||
source_len = os.stat(source_file).st_size | ||
source_file = open(source_file) | ||
|
||
with source_file: | ||
if source_len == 0: | ||
# Fall back to storing it all in memory :( | ||
data = source_file.read() | ||
source_file = io.BytesIO(data.encode('utf8')) | ||
source_len = len(data) | ||
with open(source_file_path, 'rb') as fh: | ||
source_file = BytesIO(fh.read()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we still need the data.encode('utf8') or was that a bug in the first place? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. By data.encode('utf-8') do you mean the BytesIO creation? The behavior here was improved so that a caller to Download() can either pass in a file-like object directly or a string file path. In the event they pass in a string, we have to convert it into a file like object before it's passed into HandleDataSending(). This statement was previously leaving a file handle open, so we read the contents and put it into BytesIO so that it has file-like properties. If this isn't what you meant then let me know! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh I see what you're referring too. The diff below shows us running data.encode('utf-8') on the file contents. This was a bug because the images that are Downloaded are almost always binary/outside the utf-8 space and would fail. |
||
|
||
if not source_len: | ||
if isinstance(source_file, StringIO): | ||
source_file.seek(0, os.SEEK_END) | ||
source_len = source_file.tell() | ||
source_file.seek(0) | ||
else: | ||
source_len = len(source_file) | ||
|
||
self._protocol.SendCommand(b'download', b'%08x' % source_len) | ||
return self._protocol.HandleDataSending( | ||
source_file, source_len, info_cb, progress_callback=progress_callback) | ||
self._protocol.SendCommand(b'download', b'%08x' % source_len) | ||
return self._protocol.HandleDataSending( | ||
source_file, source_len, info_cb, progress_callback=progress_callback)[0] | ||
|
||
def Flash(self, partition, timeout_ms=0, info_cb=DEFAULT_MESSAGE_CALLBACK): | ||
"""Flashes the last downloaded file to the given partition. | ||
|
@@ -396,3 +411,19 @@ def Reboot(self, target_mode=b'', timeout_ms=None): | |
def RebootBootloader(self, timeout_ms=None): | ||
"""Reboots into the bootloader, usually equiv to Reboot('bootloader').""" | ||
return self._SimpleCommand(b'reboot-bootloader', timeout_ms=timeout_ms) | ||
|
||
def Boot(self, source_file): | ||
"""Fastboot boot image by sending image from local file system then issuing the boot command | ||
|
||
Args: | ||
source_file: String file path to the image to send and boot | ||
|
||
Returns: | ||
None | ||
""" | ||
|
||
if not os.path.exists(source_file): | ||
raise ValueError("source_file must exist") | ||
|
||
self.Download(source_file) | ||
self._SimpleCommand(b'boot') |
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.
This is very important for Android 9 due to a change in struct apacket's 'data' field in adb.h