Add a script to pull launcher.db off the device and pretty print an html file with the contents.
Change-Id: I4640fad71e5f77e0dbcbe4df4204bf36a03d3562
diff --git a/print_db.py b/print_db.py
new file mode 100755
index 0000000..ebcba6c
--- /dev/null
+++ b/print_db.py
@@ -0,0 +1,220 @@
+#!/usr/bin/env python2.5
+
+import cgi
+import os
+import shutil
+import sys
+import sqlite3
+
+SCREENS = 5
+COLUMNS = 4
+ROWS = 4
+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 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>
+""")
+
+ # 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:
+ 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")
+ 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)