1#!/usr/bin/env python2.5
2
3import cgi
4import os
5import shutil
6import sys
7import sqlite3
8
9SCREENS = 5
10COLUMNS = 4
11ROWS = 4
12HOTSEAT_SIZE = 5
13CELL_SIZE = 110
14
15DIR = "db_files"
16AUTO_FILE = DIR + "/launcher.db"
17INDEX_FILE = DIR + "/index.html"
18
19def usage():
20  print "usage: print_db.py launcher.db -- prints a launcher.db"
21  print "usage: print_db.py -- 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
27
28def make_dir():
29  shutil.rmtree(DIR, True)
30  os.makedirs(DIR)
31
32def pull_file(fn):
33  print "pull_file: " + fn
34  rv = os.system("adb pull"
35    + " /data/data/com.android.launcher/databases/launcher.db"
36    + " " + fn);
37  if rv != 0:
38    print "adb pull failed"
39    sys.exit(1)
40
41def get_favorites(conn):
42  c = conn.cursor()
43  c.execute("SELECT * FROM favorites")
44  columns = [d[0] for d in c.description]
45  rows = []
46  for row in c:
47    rows.append(row)
48  return columns,rows
49
50def print_intent(out, id, i, cell):
51  if cell:
52    out.write("""<span class="intent" title="%s">shortcut</span>""" % (
53        cgi.escape(cell, True)
54      ))
55
56
57def print_icon(out, id, i, cell):
58  if cell:
59    icon_fn = "icon_%d.png" % id
60    out.write("""<img src="%s">""" % ( icon_fn ))
61    f = file(DIR + "/" + icon_fn, "w")
62    f.write(cell)
63    f.close()
64
65def print_cell(out, id, i, cell):
66  if not cell is None:
67    out.write(cgi.escape(str(cell)))
68
69FUNCTIONS = {
70  "intent": print_intent,
71  "icon": print_icon
72}
73
74def render_cell_info(out, cell, occupied):
75  if cell is None:
76    out.write("    <td width=%d height=%d></td>\n" %
77        (CELL_SIZE, CELL_SIZE))
78  elif cell == occupied:
79    pass
80  else:
81    cellX = cell["cellX"]
82    cellY = cell["cellY"]
83    spanX = cell["spanX"]
84    spanY = cell["spanY"]
85    intent = cell["intent"]
86    if intent:
87      title = "title=\"%s\"" % cgi.escape(cell["intent"], True)
88    else:
89      title = ""
90    out.write(("    <td colspan=%d rowspan=%d width=%d height=%d"
91        + " bgcolor=#dddddd align=center valign=middle %s>") % (
92          spanX, spanY,
93          (CELL_SIZE*spanX), (CELL_SIZE*spanY),
94          title))
95    itemType = cell["itemType"]
96    if itemType == 0:
97      out.write("""<img src="icon_%d.png">\n""" % ( cell["_id"] ))
98      out.write("<br/>\n")
99      out.write(cgi.escape(cell["title"]) + " <br/><i>(app)</i>")
100    elif itemType == 1:
101      out.write("""<img src="icon_%d.png">\n""" % ( cell["_id"] ))
102      out.write("<br/>\n")
103      out.write(cgi.escape(cell["title"]) + " <br/><i>(shortcut)</i>")
104    elif itemType == 2:
105      out.write("""<i>folder</i>""")
106    elif itemType == 3:
107      out.write("""<i>live folder</i>""")
108    elif itemType == 4:
109      out.write("<i>widget %d</i><br/>\n" % cell["appWidgetId"])
110    elif itemType == 1000:
111      out.write("""<i>clock</i>""")
112    elif itemType == 1001:
113      out.write("""<i>search</i>""")
114    elif itemType == 1002:
115      out.write("""<i>photo frame</i>""")
116    else:
117      out.write("<b>unknown type: %d</b>" % itemType)
118    out.write("</td>\n")
119
120def process_file(fn):
121  print "process_file: " + fn
122  conn = sqlite3.connect(fn)
123  columns,rows = get_favorites(conn)
124  data = [dict(zip(columns,row)) for row in rows]
125
126  out = file(INDEX_FILE, "w")
127  out.write("""<html>
128<head>
129<style type="text/css">
130.intent {
131  font-style: italic;
132}
133</style>
134</head>
135<body>
136""")
137
138  # Data table
139  out.write("<b>Favorites table</b><br/>\n")
140  out.write("""<html>
141<table border=1 cellspacing=0 cellpadding=4>
142<tr>
143""")
144  print_functions = []
145  for col in columns:
146    print_functions.append(FUNCTIONS.get(col, print_cell))
147  for i in range(0,len(columns)):
148    col = columns[i]
149    out.write("""  <th>%s</th>
150""" % ( col ))
151  out.write("""
152</tr>
153""")
154  for row in rows:
155    out.write("""<tr>
156""")
157    for i in range(0,len(row)):
158      cell = row[i]
159      # row[0] is always _id
160      out.write("""  <td>""")
161      print_functions[i](out, row[0], row, cell)
162      out.write("""</td>
163""")
164    out.write("""</tr>
165""")
166  out.write("""</table>
167""")
168
169  # Hotseat
170  hotseat = []
171  for i in range(0, HOTSEAT_SIZE):
172    hotseat.append(None)
173  for row in data:
174    if row["container"] != -101:
175      continue
176    screen = row["screen"]
177    hotseat[screen] = row
178  out.write("<br/><b>Hotseat</b><br/>\n")
179  out.write("<table class=layout border=1 cellspacing=0 cellpadding=4>\n")
180  for cell in hotseat:
181    render_cell_info(out, cell, None)
182  out.write("</table>\n")
183
184  # Pages
185  screens = []
186  for i in range(0,SCREENS):
187    screen = []
188    for j in range(0,ROWS):
189      m = []
190      for k in range(0,COLUMNS):
191        m.append(None)
192      screen.append(m)
193    screens.append(screen)
194  occupied = "occupied"
195  for row in data:
196    screen = screens[row["screen"]]
197    # desktop
198    if row["container"] != -100:
199      continue
200    cellX = row["cellX"]
201    cellY = row["cellY"]
202    spanX = row["spanX"]
203    spanY = row["spanY"]
204    for j in range(cellY, cellY+spanY):
205      for k in range(cellX, cellX+spanX):
206        screen[j][k] = occupied
207    screen[cellY][cellX] = row
208  i=0
209  for screen in screens:
210    out.write("<br/><b>Screen %d</b><br/>\n" % i)
211    out.write("<table class=layout border=1 cellspacing=0 cellpadding=4>\n")
212    for m in screen:
213      out.write("  <tr>\n")
214      for cell in m:
215        render_cell_info(out, cell, occupied)
216      out.write("</tr>\n")
217    out.write("</table>\n")
218    i=i+1
219
220  out.write("""
221</body>
222</html>
223""")
224
225  out.close()
226
227def main(argv):
228  if len(argv) == 1:
229    make_dir()
230    pull_file(AUTO_FILE)
231    process_file(AUTO_FILE)
232  elif len(argv) == 2:
233    make_dir()
234    process_file(argv[1])
235  else:
236    usage()
237
238if __name__=="__main__":
239  main(sys.argv)
240