print_db.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. #!/usr/bin/env python2.5
  2. import cgi
  3. import codecs
  4. import os
  5. import pprint
  6. import shutil
  7. import sys
  8. import sqlite3
  9. SCREENS = 0
  10. COLUMNS = 4
  11. ROWS = 4
  12. HOTSEAT_SIZE = 4
  13. CELL_SIZE = 110
  14. CONTAINER_DESKTOP = -100
  15. CONTAINER_HOTSEAT = -101
  16. DIR = "db_files"
  17. AUTO_FILE = DIR + "/launcher.db"
  18. INDEX_FILE = DIR + "/index.html"
  19. def usage():
  20. print "usage: print_db.py launcher.db <sw600|sw720> -- prints a launcher.db"
  21. print "usage: print_db.py <sw600|sw720> -- adb pulls a launcher.db from a device"
  22. print " and prints it"
  23. print
  24. print "The dump will be created in a directory called db_files in cwd."
  25. print "This script will delete any db_files directory you have now"
  26. def make_dir():
  27. shutil.rmtree(DIR, True)
  28. os.makedirs(DIR)
  29. def adb_root_remount():
  30. os.system("adb root")
  31. os.system("adb remount")
  32. def pull_file(fn):
  33. print "pull_file: " + fn
  34. rv = os.system("adb pull"
  35. + " /data/data/com.google.android.googlequicksearchbox/databases/launcher.db"
  36. + " " + fn);
  37. if rv != 0:
  38. print "adb pull failed"
  39. sys.exit(1)
  40. def get_favorites(conn):
  41. c = conn.cursor()
  42. c.execute("SELECT * FROM favorites")
  43. columns = [d[0] for d in c.description]
  44. rows = []
  45. for row in c:
  46. rows.append(row)
  47. return columns,rows
  48. def get_screens(conn):
  49. c = conn.cursor()
  50. c.execute("SELECT * FROM workspaceScreens")
  51. columns = [d[0] for d in c.description]
  52. rows = []
  53. for row in c:
  54. rows.append(row)
  55. return columns,rows
  56. def print_intent(out, id, i, cell):
  57. if cell:
  58. out.write("""<span class="intent" title="%s">shortcut</span>""" % (
  59. cgi.escape(cell, True)
  60. ))
  61. def print_icon(out, id, i, cell):
  62. if cell:
  63. icon_fn = "icon_%d.png" % id
  64. out.write("""<img style="width: 3em; height: 3em;" src="%s">""" % ( icon_fn ))
  65. f = file(DIR + "/" + icon_fn, "w")
  66. f.write(cell)
  67. f.close()
  68. def print_icon_type(out, id, i, cell):
  69. if cell == 0:
  70. out.write("Application (%d)" % cell)
  71. elif cell == 1:
  72. out.write("Shortcut (%d)" % cell)
  73. elif cell == 2:
  74. out.write("Folder (%d)" % cell)
  75. elif cell == 4:
  76. out.write("Widget (%d)" % cell)
  77. elif cell:
  78. out.write("%d" % cell)
  79. def print_cell(out, id, i, cell):
  80. if not cell is None:
  81. out.write(cgi.escape(unicode(cell)))
  82. FUNCTIONS = {
  83. "intent": print_intent,
  84. "icon": print_icon,
  85. "iconType": print_icon_type
  86. }
  87. def render_cell_info(out, cell, occupied):
  88. if cell is None:
  89. out.write(" <td width=%d height=%d></td>\n" %
  90. (CELL_SIZE, CELL_SIZE))
  91. elif cell == occupied:
  92. pass
  93. else:
  94. cellX = cell["cellX"]
  95. cellY = cell["cellY"]
  96. spanX = cell["spanX"]
  97. spanY = cell["spanY"]
  98. intent = cell["intent"]
  99. if intent:
  100. title = "title=\"%s\"" % cgi.escape(cell["intent"], True)
  101. else:
  102. title = ""
  103. out.write((" <td colspan=%d rowspan=%d width=%d height=%d"
  104. + " bgcolor=#dddddd align=center valign=middle %s>") % (
  105. spanX, spanY,
  106. (CELL_SIZE*spanX), (CELL_SIZE*spanY),
  107. title))
  108. itemType = cell["itemType"]
  109. if itemType == 0:
  110. out.write("""<img style="width: 4em; height: 4em;" src="icon_%d.png">\n""" % ( cell["_id"] ))
  111. out.write("<br/>\n")
  112. out.write(cgi.escape(cell["title"]) + " <br/><i>(app)</i>")
  113. elif itemType == 1:
  114. out.write("""<img style="width: 4em; height: 4em;" src="icon_%d.png">\n""" % ( cell["_id"] ))
  115. out.write("<br/>\n")
  116. out.write(cgi.escape(cell["title"]) + " <br/><i>(shortcut)</i>")
  117. elif itemType == 2:
  118. out.write("""<i>folder</i>""")
  119. elif itemType == 4:
  120. out.write("<i>widget %d</i><br/>\n" % cell["appWidgetId"])
  121. else:
  122. out.write("<b>unknown type: %d</b>" % itemType)
  123. out.write("</td>\n")
  124. def render_screen_info(out, screen):
  125. out.write("<tr>")
  126. out.write("<td>%s</td>" % (screen["_id"]))
  127. out.write("<td>%s</td>" % (screen["screenRank"]))
  128. out.write("</tr>")
  129. def process_file(fn):
  130. global SCREENS, COLUMNS, ROWS, HOTSEAT_SIZE
  131. print "process_file: " + fn
  132. conn = sqlite3.connect(fn)
  133. columns,rows = get_favorites(conn)
  134. screenCols, screenRows = get_screens(conn)
  135. data = [dict(zip(columns,row)) for row in rows]
  136. screenData = [dict(zip(screenCols, screenRow)) for screenRow in screenRows]
  137. # Calculate the proper number of screens, columns, and rows in this db
  138. screensIdMap = []
  139. hotseatIdMap = []
  140. HOTSEAT_SIZE = 0
  141. for d in data:
  142. if d["spanX"] is None:
  143. d["spanX"] = 1
  144. if d["spanY"] is None:
  145. d["spanY"] = 1
  146. if d["container"] == CONTAINER_DESKTOP:
  147. if d["screen"] not in screensIdMap:
  148. screensIdMap.append(d["screen"])
  149. COLUMNS = max(COLUMNS, d["cellX"] + d["spanX"])
  150. ROWS = max(ROWS, d["cellX"] + d["spanX"])
  151. elif d["container"] == CONTAINER_HOTSEAT:
  152. hotseatIdMap.append(d["screen"])
  153. HOTSEAT_SIZE = max(HOTSEAT_SIZE, d["screen"] + 1)
  154. SCREENS = len(screensIdMap)
  155. out = codecs.open(INDEX_FILE, encoding="utf-8", mode="w")
  156. out.write("""<html>
  157. <head>
  158. <style type="text/css">
  159. .intent {
  160. font-style: italic;
  161. }
  162. </style>
  163. </head>
  164. <body>
  165. """)
  166. # Data table
  167. out.write("<b>Favorites table</b><br/>\n")
  168. out.write("""<html>
  169. <table border=1 cellspacing=0 cellpadding=4>
  170. <tr>
  171. """)
  172. print_functions = []
  173. for col in columns:
  174. print_functions.append(FUNCTIONS.get(col, print_cell))
  175. for i in range(0,len(columns)):
  176. col = columns[i]
  177. out.write(""" <th>%s</th>
  178. """ % ( col ))
  179. out.write("""
  180. </tr>
  181. """)
  182. for row in rows:
  183. out.write("""<tr>
  184. """)
  185. for i in range(0,len(row)):
  186. cell = row[i]
  187. # row[0] is always _id
  188. out.write(""" <td>""")
  189. print_functions[i](out, row[0], row, cell)
  190. out.write("""</td>
  191. """)
  192. out.write("""</tr>
  193. """)
  194. out.write("""</table>
  195. """)
  196. # Screens
  197. out.write("<br/><b>Screens</b><br/>\n")
  198. out.write("<table class=layout border=1 cellspacing=0 cellpadding=4>\n")
  199. out.write("<tr><td>Screen ID</td><td>Rank</td></tr>\n")
  200. for screen in screenData:
  201. render_screen_info(out, screen)
  202. out.write("</table>\n")
  203. # Hotseat
  204. hotseat = []
  205. for i in range(0, HOTSEAT_SIZE):
  206. hotseat.append(None)
  207. for row in data:
  208. if row["container"] != CONTAINER_HOTSEAT:
  209. continue
  210. screen = row["screen"]
  211. hotseat[screen] = row
  212. out.write("<br/><b>Hotseat</b><br/>\n")
  213. out.write("<table class=layout border=1 cellspacing=0 cellpadding=4>\n")
  214. for cell in hotseat:
  215. render_cell_info(out, cell, None)
  216. out.write("</table>\n")
  217. # Pages
  218. screens = []
  219. for i in range(0,SCREENS):
  220. screen = []
  221. for j in range(0,ROWS):
  222. m = []
  223. for k in range(0,COLUMNS):
  224. m.append(None)
  225. screen.append(m)
  226. screens.append(screen)
  227. occupied = "occupied"
  228. for row in data:
  229. # desktop
  230. if row["container"] != CONTAINER_DESKTOP:
  231. continue
  232. screen = screens[screensIdMap.index(row["screen"])]
  233. cellX = row["cellX"]
  234. cellY = row["cellY"]
  235. spanX = row["spanX"]
  236. spanY = row["spanY"]
  237. for j in range(cellY, cellY+spanY):
  238. for k in range(cellX, cellX+spanX):
  239. screen[j][k] = occupied
  240. screen[cellY][cellX] = row
  241. i=0
  242. for screen in screens:
  243. out.write("<br/><b>Screen %d</b><br/>\n" % i)
  244. out.write("<table class=layout border=1 cellspacing=0 cellpadding=4>\n")
  245. for m in screen:
  246. out.write(" <tr>\n")
  247. for cell in m:
  248. render_cell_info(out, cell, occupied)
  249. out.write("</tr>\n")
  250. out.write("</table>\n")
  251. i=i+1
  252. out.write("""
  253. </body>
  254. </html>
  255. """)
  256. out.close()
  257. def updateDeviceClassConstants(str):
  258. global SCREENS, COLUMNS, ROWS, HOTSEAT_SIZE
  259. devClass = str.lower()
  260. if devClass == "sw600":
  261. COLUMNS = 6
  262. ROWS = 6
  263. HOTSEAT_SIZE = 6
  264. return True
  265. elif devClass == "sw720":
  266. COLUMNS = 8
  267. ROWS = 6
  268. HOTSEAT_SIZE = 8
  269. return True
  270. return False
  271. def main(argv):
  272. if len(argv) == 1 or (len(argv) == 2 and updateDeviceClassConstants(argv[1])):
  273. make_dir()
  274. adb_root_remount()
  275. pull_file(AUTO_FILE)
  276. process_file(AUTO_FILE)
  277. elif len(argv) == 2 or (len(argv) == 3 and updateDeviceClassConstants(argv[2])):
  278. make_dir()
  279. process_file(argv[1])
  280. else:
  281. usage()
  282. if __name__=="__main__":
  283. main(sys.argv)