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

@@ -77,16 +77,30 @@
 bprocess
+%0Aimport random
 %0A%0AANDROI
@@ -397,32 +397,45 @@
 ice_call_string(
+service_call(
 %5B%22iphonesubinfo%22
@@ -459,16 +459,17 @@
 (slot)%5D)
+)
 %0A  if no
@@ -483,31 +483,101 @@
     
-ret = %22000000000000000%22
+# allow non android to be identified differently%0A    ret = %22%25015d%22 %25 random.randint(0, 1%3C%3C32)
 %0A  r
@@ -748,16 +748,29 @@
 _string(
+service_call(
 %5B%22iphone
@@ -784,16 +784,17 @@
 %22, %227%22%5D)
+)
 %0A  if re
@@ -1134,30 +1134,24 @@
 t%0A  %5D)%0A%0Adef 
-parse_
 service_call
@@ -1154,33 +1154,187 @@
 call
-_unpack(
+(call):%0A  if not ANDROID:%0A    return None%0A%0A  ret = subprocess.check_output(%5B%22service%22, %22
 call
+%22
 , 
-fmt)
+*call%5D, encoding='utf8').strip()%0A  if 'Parcel' not in ret
 :%0A  
+ 
-r =
+ return None%0A%0A  return
  par
@@ -1347,37 +1347,76 @@
 vice_call_bytes(
-call)
+ret)%0A%0Adef parse_service_call_unpack(r, fmt):
 %0A  try:%0A    retu
@@ -1514,51 +1514,11 @@
 ing(
-call):%0A  r = parse_service_call_bytes(call)
+r):
 %0A  t
@@ -1901,176 +1901,13 @@
 tes(
-call):%0A  if not ANDROID:%0A    return None%0A  ret = subprocess.check_output(%5B%22service%22, %22call%22, *call%5D, encoding='utf8').strip()%0A  if 'Parcel' not in ret:%0A    return None%0A
+ret):
 %0A  t

update common/android.py