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