| #!/usr/bin/env python2.5 |
| |
| import cgi |
| import os |
| import shutil |
| import sys |
| import sqlite3 |
| |
| SCREENS = 5 |
| COLUMNS = 4 |
| ROWS = 4 |
| HOTSEAT_SIZE = 5 |
| CELL_SIZE = 110 |
| |
| DIR = "db_files" |
| AUTO_FILE = DIR + "/launcher.db" |
| INDEX_FILE = DIR + "/index.html" |
| |
| def usage(): |
| print "usage: print_db.py launcher.db -- prints a launcher.db" |
| print "usage: print_db.py -- adb pulls a launcher.db from a device" |
| print " and prints it" |
| print |
| print "The dump will be created in a directory called db_files in cwd." |
| print "This script will delete any db_files directory you have now" |
| |
| |
| def make_dir(): |
| shutil.rmtree(DIR, True) |
| os.makedirs(DIR) |
| |
| def pull_file(fn): |
| print "pull_file: " + fn |
| rv = os.system("adb pull" |
| + " /data/data/com.android.launcher/databases/launcher.db" |
| + " " + fn); |
| if rv != 0: |
| print "adb pull failed" |
| sys.exit(1) |
| |
| def get_favorites(conn): |
| c = conn.cursor() |
| c.execute("SELECT * FROM favorites") |
| columns = [d[0] for d in c.description] |
| rows = [] |
| for row in c: |
| rows.append(row) |
| return columns,rows |
| |
| def print_intent(out, id, i, cell): |
| if cell: |
| out.write("""<span class="intent" title="%s">shortcut</span>""" % ( |
| cgi.escape(cell, True) |
| )) |
| |
| |
| def print_icon(out, id, i, cell): |
| if cell: |
| icon_fn = "icon_%d.png" % id |
| out.write("""<img src="%s">""" % ( icon_fn )) |
| f = file(DIR + "/" + icon_fn, "w") |
| f.write(cell) |
| f.close() |
| |
| def print_cell(out, id, i, cell): |
| if not cell is None: |
| out.write(cgi.escape(str(cell))) |
| |
| FUNCTIONS = { |
| "intent": print_intent, |
| "icon": print_icon |
| } |
| |
| def render_cell_info(out, cell, occupied): |
| if cell is None: |
| out.write(" <td width=%d height=%d></td>\n" % |
| (CELL_SIZE, CELL_SIZE)) |
| elif cell == occupied: |
| pass |
| else: |
| cellX = cell["cellX"] |
| cellY = cell["cellY"] |
| spanX = cell["spanX"] |
| spanY = cell["spanY"] |
| intent = cell["intent"] |
| if intent: |
| title = "title=\"%s\"" % cgi.escape(cell["intent"], True) |
| else: |
| title = "" |
| out.write((" <td colspan=%d rowspan=%d width=%d height=%d" |
| + " bgcolor=#dddddd align=center valign=middle %s>") % ( |
| spanX, spanY, |
| (CELL_SIZE*spanX), (CELL_SIZE*spanY), |
| title)) |
| itemType = cell["itemType"] |
| if itemType == 0: |
| out.write("""<img src="icon_%d.png">\n""" % ( cell["_id"] )) |
| out.write("<br/>\n") |
| out.write(cgi.escape(cell["title"]) + " <br/><i>(app)</i>") |
| elif itemType == 1: |
| out.write("""<img src="icon_%d.png">\n""" % ( cell["_id"] )) |
| out.write("<br/>\n") |
| out.write(cgi.escape(cell["title"]) + " <br/><i>(shortcut)</i>") |
| elif itemType == 2: |
| out.write("""<i>folder</i>""") |
| elif itemType == 3: |
| out.write("""<i>live folder</i>""") |
| elif itemType == 4: |
| out.write("<i>widget %d</i><br/>\n" % cell["appWidgetId"]) |
| elif itemType == 1000: |
| out.write("""<i>clock</i>""") |
| elif itemType == 1001: |
| out.write("""<i>search</i>""") |
| elif itemType == 1002: |
| out.write("""<i>photo frame</i>""") |
| else: |
| out.write("<b>unknown type: %d</b>" % itemType) |
| out.write("</td>\n") |
| |
| def process_file(fn): |
| print "process_file: " + fn |
| conn = sqlite3.connect(fn) |
| columns,rows = get_favorites(conn) |
| data = [dict(zip(columns,row)) for row in rows] |
| |
| out = file(INDEX_FILE, "w") |
| out.write("""<html> |
| <head> |
| <style type="text/css"> |
| .intent { |
| font-style: italic; |
| } |
| </style> |
| </head> |
| <body> |
| """) |
| |
| # Data table |
| out.write("<b>Favorites table</b><br/>\n") |
| out.write("""<html> |
| <table border=1 cellspacing=0 cellpadding=4> |
| <tr> |
| """) |
| print_functions = [] |
| for col in columns: |
| print_functions.append(FUNCTIONS.get(col, print_cell)) |
| for i in range(0,len(columns)): |
| col = columns[i] |
| out.write(""" <th>%s</th> |
| """ % ( col )) |
| out.write(""" |
| </tr> |
| """) |
| for row in rows: |
| out.write("""<tr> |
| """) |
| for i in range(0,len(row)): |
| cell = row[i] |
| # row[0] is always _id |
| out.write(""" <td>""") |
| print_functions[i](out, row[0], row, cell) |
| out.write("""</td> |
| """) |
| out.write("""</tr> |
| """) |
| out.write("""</table> |
| """) |
| |
| # Hotseat |
| hotseat = [] |
| for i in range(0, HOTSEAT_SIZE): |
| hotseat.append(None) |
| for row in data: |
| if row["container"] != -101: |
| continue |
| screen = row["screen"] |
| hotseat[screen] = row |
| out.write("<br/><b>Hotseat</b><br/>\n") |
| out.write("<table class=layout border=1 cellspacing=0 cellpadding=4>\n") |
| for cell in hotseat: |
| render_cell_info(out, cell, None) |
| out.write("</table>\n") |
| |
| # Pages |
| screens = [] |
| for i in range(0,SCREENS): |
| screen = [] |
| for j in range(0,ROWS): |
| m = [] |
| for k in range(0,COLUMNS): |
| m.append(None) |
| screen.append(m) |
| screens.append(screen) |
| occupied = "occupied" |
| for row in data: |
| screen = screens[row["screen"]] |
| # desktop |
| if row["container"] != -100: |
| continue |
| cellX = row["cellX"] |
| cellY = row["cellY"] |
| spanX = row["spanX"] |
| spanY = row["spanY"] |
| for j in range(cellY, cellY+spanY): |
| for k in range(cellX, cellX+spanX): |
| screen[j][k] = occupied |
| screen[cellY][cellX] = row |
| i=0 |
| for screen in screens: |
| out.write("<br/><b>Screen %d</b><br/>\n" % i) |
| out.write("<table class=layout border=1 cellspacing=0 cellpadding=4>\n") |
| for m in screen: |
| out.write(" <tr>\n") |
| for cell in m: |
| render_cell_info(out, cell, occupied) |
| out.write("</tr>\n") |
| out.write("</table>\n") |
| i=i+1 |
| |
| out.write(""" |
| </body> |
| </html> |
| """) |
| |
| out.close() |
| |
| def main(argv): |
| if len(argv) == 1: |
| make_dir() |
| pull_file(AUTO_FILE) |
| process_file(AUTO_FILE) |
| elif len(argv) == 2: |
| make_dir() |
| process_file(argv[1]) |
| else: |
| usage() |
| |
| if __name__=="__main__": |
| main(sys.argv) |