blob: 6caa7bb87a56ad7ea58b549c8df8ae8f7b4d4c3e [file] [log] [blame]
Joe Onorato6f9d4bd2010-09-29 17:43:46 -07001#!/usr/bin/env python2.5
2
3import cgi
Winson Chung88381732013-07-12 13:41:18 -07004import codecs
Joe Onorato6f9d4bd2010-09-29 17:43:46 -07005import os
Winson Chung88381732013-07-12 13:41:18 -07006import pprint
Joe Onorato6f9d4bd2010-09-29 17:43:46 -07007import shutil
8import sys
9import sqlite3
10
Winson Chung88381732013-07-12 13:41:18 -070011SCREENS = 0
Joe Onorato6f9d4bd2010-09-29 17:43:46 -070012COLUMNS = 4
13ROWS = 4
Winson Chung88381732013-07-12 13:41:18 -070014HOTSEAT_SIZE = 4
Joe Onorato6f9d4bd2010-09-29 17:43:46 -070015CELL_SIZE = 110
16
Winson Chung88381732013-07-12 13:41:18 -070017CONTAINER_DESKTOP = -100
18CONTAINER_HOTSEAT = -101
19
Joe Onorato6f9d4bd2010-09-29 17:43:46 -070020DIR = "db_files"
21AUTO_FILE = DIR + "/launcher.db"
22INDEX_FILE = DIR + "/index.html"
23
24def usage():
Winson Chung88381732013-07-12 13:41:18 -070025 print "usage: print_db.py launcher.db <sw600|sw720> -- prints a launcher.db"
26 print "usage: print_db.py <sw600|sw720> -- adb pulls a launcher.db from a device"
Joe Onorato6f9d4bd2010-09-29 17:43:46 -070027 print " and prints it"
28 print
29 print "The dump will be created in a directory called db_files in cwd."
30 print "This script will delete any db_files directory you have now"
31
32
33def make_dir():
34 shutil.rmtree(DIR, True)
35 os.makedirs(DIR)
36
37def pull_file(fn):
38 print "pull_file: " + fn
39 rv = os.system("adb pull"
Winson Chung88381732013-07-12 13:41:18 -070040 + " /data/data/com.google.android.googlequicksearchbox/databases/launcher.db"
Joe Onorato6f9d4bd2010-09-29 17:43:46 -070041 + " " + fn);
42 if rv != 0:
43 print "adb pull failed"
44 sys.exit(1)
45
46def get_favorites(conn):
47 c = conn.cursor()
48 c.execute("SELECT * FROM favorites")
49 columns = [d[0] for d in c.description]
50 rows = []
51 for row in c:
52 rows.append(row)
53 return columns,rows
54
55def print_intent(out, id, i, cell):
56 if cell:
57 out.write("""<span class="intent" title="%s">shortcut</span>""" % (
58 cgi.escape(cell, True)
59 ))
60
61
62def print_icon(out, id, i, cell):
63 if cell:
64 icon_fn = "icon_%d.png" % id
Winson Chung88381732013-07-12 13:41:18 -070065 out.write("""<img style="width: 3em; height: 3em;" src="%s">""" % ( icon_fn ))
Joe Onorato6f9d4bd2010-09-29 17:43:46 -070066 f = file(DIR + "/" + icon_fn, "w")
67 f.write(cell)
68 f.close()
69
Winson Chung88381732013-07-12 13:41:18 -070070def print_icon_type(out, id, i, cell):
71 if cell == 0:
72 out.write("Application (%d)" % cell)
73 elif cell == 1:
74 out.write("Shortcut (%d)" % cell)
75 elif cell == 2:
76 out.write("Folder (%d)" % cell)
77 elif cell == 4:
78 out.write("Widget (%d)" % cell)
79 elif cell:
80 out.write("%d" % cell)
81
Joe Onorato6f9d4bd2010-09-29 17:43:46 -070082def print_cell(out, id, i, cell):
83 if not cell is None:
Winson Chung88381732013-07-12 13:41:18 -070084 out.write(cgi.escape(unicode(cell)))
Joe Onorato6f9d4bd2010-09-29 17:43:46 -070085
86FUNCTIONS = {
87 "intent": print_intent,
Winson Chung88381732013-07-12 13:41:18 -070088 "icon": print_icon,
89 "iconType": print_icon_type
Joe Onorato6f9d4bd2010-09-29 17:43:46 -070090}
91
Winson Chungbfc003a2011-08-24 11:32:02 -070092def render_cell_info(out, cell, occupied):
93 if cell is None:
94 out.write(" <td width=%d height=%d></td>\n" %
95 (CELL_SIZE, CELL_SIZE))
96 elif cell == occupied:
97 pass
98 else:
99 cellX = cell["cellX"]
100 cellY = cell["cellY"]
101 spanX = cell["spanX"]
102 spanY = cell["spanY"]
103 intent = cell["intent"]
104 if intent:
105 title = "title=\"%s\"" % cgi.escape(cell["intent"], True)
106 else:
107 title = ""
108 out.write((" <td colspan=%d rowspan=%d width=%d height=%d"
109 + " bgcolor=#dddddd align=center valign=middle %s>") % (
110 spanX, spanY,
111 (CELL_SIZE*spanX), (CELL_SIZE*spanY),
112 title))
113 itemType = cell["itemType"]
114 if itemType == 0:
Winson Chung88381732013-07-12 13:41:18 -0700115 out.write("""<img style="width: 4em; height: 4em;" src="icon_%d.png">\n""" % ( cell["_id"] ))
Winson Chungbfc003a2011-08-24 11:32:02 -0700116 out.write("<br/>\n")
117 out.write(cgi.escape(cell["title"]) + " <br/><i>(app)</i>")
118 elif itemType == 1:
Winson Chung88381732013-07-12 13:41:18 -0700119 out.write("""<img style="width: 4em; height: 4em;" src="icon_%d.png">\n""" % ( cell["_id"] ))
Winson Chungbfc003a2011-08-24 11:32:02 -0700120 out.write("<br/>\n")
121 out.write(cgi.escape(cell["title"]) + " <br/><i>(shortcut)</i>")
122 elif itemType == 2:
123 out.write("""<i>folder</i>""")
Winson Chungbfc003a2011-08-24 11:32:02 -0700124 elif itemType == 4:
125 out.write("<i>widget %d</i><br/>\n" % cell["appWidgetId"])
Winson Chungbfc003a2011-08-24 11:32:02 -0700126 else:
127 out.write("<b>unknown type: %d</b>" % itemType)
128 out.write("</td>\n")
129
Joe Onorato6f9d4bd2010-09-29 17:43:46 -0700130def process_file(fn):
Winson Chung88381732013-07-12 13:41:18 -0700131 global SCREENS, COLUMNS, ROWS, HOTSEAT_SIZE
Joe Onorato6f9d4bd2010-09-29 17:43:46 -0700132 print "process_file: " + fn
133 conn = sqlite3.connect(fn)
134 columns,rows = get_favorites(conn)
Winson Chung88381732013-07-12 13:41:18 -0700135
Joe Onorato6f9d4bd2010-09-29 17:43:46 -0700136 data = [dict(zip(columns,row)) for row in rows]
137
Winson Chung88381732013-07-12 13:41:18 -0700138 # Calculate the proper number of screens, columns, and rows in this db
139 screensIdMap = []
140 hotseatIdMap = []
141 HOTSEAT_SIZE = 0
142 for d in data:
Winson Chung8481e322013-08-09 16:06:38 -0700143 if d["spanX"] is None:
144 d["spanX"] = 1
145 if d["spanY"] is None:
146 d["spanY"] = 1
Winson Chung88381732013-07-12 13:41:18 -0700147 if d["container"] == CONTAINER_DESKTOP:
148 if d["screen"] not in screensIdMap:
149 screensIdMap.append(d["screen"])
150 COLUMNS = max(COLUMNS, d["cellX"] + d["spanX"])
151 ROWS = max(ROWS, d["cellX"] + d["spanX"])
152 elif d["container"] == CONTAINER_HOTSEAT:
153 hotseatIdMap.append(d["screen"])
154 HOTSEAT_SIZE = max(HOTSEAT_SIZE, d["screen"] + 1)
155 SCREENS = len(screensIdMap)
156
157 out = codecs.open(INDEX_FILE, encoding="utf-8", mode="w")
Joe Onorato6f9d4bd2010-09-29 17:43:46 -0700158 out.write("""<html>
159<head>
160<style type="text/css">
161.intent {
162 font-style: italic;
163}
164</style>
165</head>
166<body>
167""")
168
169 # Data table
170 out.write("<b>Favorites table</b><br/>\n")
171 out.write("""<html>
172<table border=1 cellspacing=0 cellpadding=4>
173<tr>
174""")
175 print_functions = []
176 for col in columns:
177 print_functions.append(FUNCTIONS.get(col, print_cell))
178 for i in range(0,len(columns)):
179 col = columns[i]
180 out.write(""" <th>%s</th>
181""" % ( col ))
182 out.write("""
183</tr>
184""")
Winson Chung88381732013-07-12 13:41:18 -0700185
Joe Onorato6f9d4bd2010-09-29 17:43:46 -0700186 for row in rows:
187 out.write("""<tr>
188""")
189 for i in range(0,len(row)):
190 cell = row[i]
191 # row[0] is always _id
192 out.write(""" <td>""")
193 print_functions[i](out, row[0], row, cell)
194 out.write("""</td>
195""")
196 out.write("""</tr>
197""")
198 out.write("""</table>
199""")
200
Winson Chungbfc003a2011-08-24 11:32:02 -0700201 # Hotseat
202 hotseat = []
203 for i in range(0, HOTSEAT_SIZE):
204 hotseat.append(None)
205 for row in data:
Winson Chung88381732013-07-12 13:41:18 -0700206 if row["container"] != CONTAINER_HOTSEAT:
Winson Chungbfc003a2011-08-24 11:32:02 -0700207 continue
208 screen = row["screen"]
209 hotseat[screen] = row
210 out.write("<br/><b>Hotseat</b><br/>\n")
211 out.write("<table class=layout border=1 cellspacing=0 cellpadding=4>\n")
212 for cell in hotseat:
213 render_cell_info(out, cell, None)
214 out.write("</table>\n")
215
Joe Onorato6f9d4bd2010-09-29 17:43:46 -0700216 # Pages
217 screens = []
218 for i in range(0,SCREENS):
219 screen = []
220 for j in range(0,ROWS):
221 m = []
222 for k in range(0,COLUMNS):
223 m.append(None)
224 screen.append(m)
225 screens.append(screen)
226 occupied = "occupied"
227 for row in data:
Joe Onorato6f9d4bd2010-09-29 17:43:46 -0700228 # desktop
Winson Chung88381732013-07-12 13:41:18 -0700229 if row["container"] != CONTAINER_DESKTOP:
Joe Onorato6f9d4bd2010-09-29 17:43:46 -0700230 continue
Winson Chung88381732013-07-12 13:41:18 -0700231 screen = screens[screensIdMap.index(row["screen"])]
Joe Onorato6f9d4bd2010-09-29 17:43:46 -0700232 cellX = row["cellX"]
233 cellY = row["cellY"]
234 spanX = row["spanX"]
235 spanY = row["spanY"]
236 for j in range(cellY, cellY+spanY):
237 for k in range(cellX, cellX+spanX):
238 screen[j][k] = occupied
239 screen[cellY][cellX] = row
240 i=0
241 for screen in screens:
242 out.write("<br/><b>Screen %d</b><br/>\n" % i)
243 out.write("<table class=layout border=1 cellspacing=0 cellpadding=4>\n")
244 for m in screen:
245 out.write(" <tr>\n")
246 for cell in m:
Winson Chungbfc003a2011-08-24 11:32:02 -0700247 render_cell_info(out, cell, occupied)
Joe Onorato6f9d4bd2010-09-29 17:43:46 -0700248 out.write("</tr>\n")
249 out.write("</table>\n")
250 i=i+1
251
252 out.write("""
253</body>
254</html>
255""")
256
257 out.close()
258
Winson Chung88381732013-07-12 13:41:18 -0700259def updateDeviceClassConstants(str):
260 global SCREENS, COLUMNS, ROWS, HOTSEAT_SIZE
261 devClass = str.lower()
262 if devClass == "sw600":
263 COLUMNS = 6
264 ROWS = 6
265 HOTSEAT_SIZE = 6
266 return True
267 elif devClass == "sw720":
268 COLUMNS = 8
269 ROWS = 6
270 HOTSEAT_SIZE = 8
271 return True
272 return False
273
Joe Onorato6f9d4bd2010-09-29 17:43:46 -0700274def main(argv):
Winson Chung88381732013-07-12 13:41:18 -0700275 if len(argv) == 1 or (len(argv) == 2 and updateDeviceClassConstants(argv[1])):
Joe Onorato6f9d4bd2010-09-29 17:43:46 -0700276 make_dir()
277 pull_file(AUTO_FILE)
278 process_file(AUTO_FILE)
Winson Chung88381732013-07-12 13:41:18 -0700279 elif len(argv) == 2 or (len(argv) == 3 and updateDeviceClassConstants(argv[2])):
Joe Onorato6f9d4bd2010-09-29 17:43:46 -0700280 make_dir()
281 process_file(argv[1])
282 else:
283 usage()
284
285if __name__=="__main__":
286 main(sys.argv)