You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							87 lines
						
					
					
						
							1.9 KiB
						
					
					
				
			
		
		
	
	
							87 lines
						
					
					
						
							1.9 KiB
						
					
					
				import os
 | 
						|
import binascii
 | 
						|
import itertools
 | 
						|
import re
 | 
						|
import struct
 | 
						|
import subprocess
 | 
						|
 | 
						|
ANDROID = os.path.isfile('/EON')
 | 
						|
 | 
						|
def getprop(key):
 | 
						|
  if not ANDROID:
 | 
						|
    return ""
 | 
						|
  return subprocess.check_output(["getprop", key], encoding='utf8').strip()
 | 
						|
 | 
						|
def get_imei(slot):
 | 
						|
  slot = str(slot)
 | 
						|
  if slot not in ("0", "1"):
 | 
						|
    raise ValueError("SIM slot must be 0 or 1")
 | 
						|
 | 
						|
  ret = parse_service_call_string(["iphonesubinfo", "3" ,"i32", str(slot)])
 | 
						|
  if not ret:
 | 
						|
    ret = "000000000000000"
 | 
						|
  return ret
 | 
						|
 | 
						|
def get_serial():
 | 
						|
  ret = getprop("ro.serialno")
 | 
						|
  if ret == "":
 | 
						|
    ret = "cccccccc"
 | 
						|
  return ret
 | 
						|
 | 
						|
def get_subscriber_info():
 | 
						|
  ret = parse_service_call_string(["iphonesubinfo", "7"])
 | 
						|
  if ret is None or len(ret) < 8:
 | 
						|
    return ""
 | 
						|
  return ret
 | 
						|
 | 
						|
def reboot(reason=None):
 | 
						|
  if reason is None:
 | 
						|
    reason_args = ["null"]
 | 
						|
  else:
 | 
						|
    reason_args = ["s16", reason]
 | 
						|
 | 
						|
  subprocess.check_output([
 | 
						|
    "service", "call", "power", "16", # IPowerManager.reboot
 | 
						|
    "i32", "0", # no confirmation,
 | 
						|
    *reason_args,
 | 
						|
    "i32", "1" # wait
 | 
						|
  ])
 | 
						|
 | 
						|
def parse_service_call_unpack(call, fmt):
 | 
						|
  r = parse_service_call_bytes(call)
 | 
						|
  try:
 | 
						|
    return struct.unpack(fmt, r)[0]
 | 
						|
  except Exception:
 | 
						|
    return None
 | 
						|
 | 
						|
def parse_service_call_string(call):
 | 
						|
  r = parse_service_call_bytes(call)
 | 
						|
  try:
 | 
						|
    r = r[8:] # Cut off length field
 | 
						|
    r = r.decode('utf_16_be')
 | 
						|
 | 
						|
    # All pairs of two characters seem to be swapped. Not sure why
 | 
						|
    result = ""
 | 
						|
    for a, b, in itertools.zip_longest(r[::2], r[1::2], fillvalue='\x00'):
 | 
						|
        result += b + a
 | 
						|
 | 
						|
    result = result.replace('\x00', '')
 | 
						|
 | 
						|
    return result
 | 
						|
  except Exception:
 | 
						|
    return None
 | 
						|
 | 
						|
def parse_service_call_bytes(call):
 | 
						|
  if not ANDROID:
 | 
						|
    return None
 | 
						|
  ret = subprocess.check_output(["service", "call", *call], encoding='utf8').strip()
 | 
						|
  if 'Parcel' not in ret:
 | 
						|
    return None
 | 
						|
 | 
						|
  try:
 | 
						|
    r = b""
 | 
						|
    for hex_part in re.findall(r'[ (]([0-9a-f]{8})', ret):
 | 
						|
      r += binascii.unhexlify(hex_part)
 | 
						|
    return r
 | 
						|
  except Exception:
 | 
						|
    return None
 | 
						|
 |