print_db.py 7.93 KB
Newer Older
1 2 3
#!/usr/bin/env python2.5

import cgi
4
import codecs
5
import os
6
import pprint
7 8 9 10
import shutil
import sys
import sqlite3

11
SCREENS = 0
12 13
COLUMNS = 4
ROWS = 4
14
HOTSEAT_SIZE = 4
15 16
CELL_SIZE = 110

17 18 19
CONTAINER_DESKTOP = -100
CONTAINER_HOTSEAT = -101

20 21 22 23 24
DIR = "db_files"
AUTO_FILE = DIR + "/launcher.db"
INDEX_FILE = DIR + "/index.html"

def usage():
25 26
  print "usage: print_db.py launcher.db <sw600|sw720> -- prints a launcher.db"
  print "usage: print_db.py <sw600|sw720> -- adb pulls a launcher.db from a device"
27 28 29 30 31 32 33 34 35 36
  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)

37 38 39 40
def adb_root_remount():
  os.system("adb root")
  os.system("adb remount")

41 42 43
def pull_file(fn):
  print "pull_file: " + fn
  rv = os.system("adb pull"
44
    + " /data/data/com.google.android.googlequicksearchbox/databases/launcher.db"
45 46 47 48 49 50 51 52 53 54 55 56 57 58
    + " " + 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

59 60 61 62 63 64 65 66 67
def get_screens(conn):
  c = conn.cursor()
  c.execute("SELECT * FROM workspaceScreens")
  columns = [d[0] for d in c.description]
  rows = []
  for row in c:
    rows.append(row)
  return columns,rows

68 69 70 71 72 73 74 75 76 77
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
78
    out.write("""<img style="width: 3em; height: 3em;" src="%s">""" % ( icon_fn ))
79 80 81 82
    f = file(DIR + "/" + icon_fn, "w")
    f.write(cell)
    f.close()

83 84 85 86 87 88 89 90 91 92 93 94
def print_icon_type(out, id, i, cell):
  if cell == 0:
    out.write("Application (%d)" % cell)
  elif cell == 1:
    out.write("Shortcut (%d)" % cell)
  elif cell == 2:
    out.write("Folder (%d)" % cell)
  elif cell == 4:
    out.write("Widget (%d)" % cell)
  elif cell:
    out.write("%d" % cell)

95 96
def print_cell(out, id, i, cell):
  if not cell is None:
97
    out.write(cgi.escape(unicode(cell)))
98 99 100

FUNCTIONS = {
  "intent": print_intent,
101 102
  "icon": print_icon,
  "iconType": print_icon_type
103 104
}

105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
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:
128
      out.write("""<img style="width: 4em; height: 4em;" src="icon_%d.png">\n""" % ( cell["_id"] ))
129 130 131
      out.write("<br/>\n")
      out.write(cgi.escape(cell["title"]) + " <br/><i>(app)</i>")
    elif itemType == 1:
132
      out.write("""<img style="width: 4em; height: 4em;" src="icon_%d.png">\n""" % ( cell["_id"] ))
133 134 135 136 137 138 139 140 141 142
      out.write("<br/>\n")
      out.write(cgi.escape(cell["title"]) + " <br/><i>(shortcut)</i>")
    elif itemType == 2:
      out.write("""<i>folder</i>""")
    elif itemType == 4:
      out.write("<i>widget %d</i><br/>\n" % cell["appWidgetId"])
    else:
      out.write("<b>unknown type: %d</b>" % itemType)
    out.write("</td>\n")

143 144 145 146 147 148
def render_screen_info(out, screen):
  out.write("<tr>")
  out.write("<td>%s</td>" % (screen["_id"]))
  out.write("<td>%s</td>" % (screen["screenRank"]))
  out.write("</tr>")

149
def process_file(fn):
150
  global SCREENS, COLUMNS, ROWS, HOTSEAT_SIZE
151 152 153
  print "process_file: " + fn
  conn = sqlite3.connect(fn)
  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 160 161 162 163
  # Calculate the proper number of screens, columns, and rows in this db
  screensIdMap = []
  hotseatIdMap = []
  HOTSEAT_SIZE = 0
  for d in data:
164 165 166 167
    if d["spanX"] is None:
      d["spanX"] = 1
    if d["spanY"] is None:
      d["spanY"] = 1
168 169 170 171 172 173 174 175 176 177 178
    if d["container"] == CONTAINER_DESKTOP:
      if d["screen"] not in screensIdMap:
        screensIdMap.append(d["screen"])
      COLUMNS = max(COLUMNS, d["cellX"] + d["spanX"])
      ROWS = max(ROWS, d["cellX"] + d["spanX"])
    elif d["container"] == CONTAINER_HOTSEAT:
      hotseatIdMap.append(d["screen"])
      HOTSEAT_SIZE = max(HOTSEAT_SIZE, d["screen"] + 1)
  SCREENS = len(screensIdMap)

  out = codecs.open(INDEX_FILE, encoding="utf-8", mode="w")
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
  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>
""")
206

207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
  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>
""")

222 223 224 225 226 227 228 229
  # Screens
  out.write("<br/><b>Screens</b><br/>\n")
  out.write("<table class=layout border=1 cellspacing=0 cellpadding=4>\n")
  out.write("<tr><td>Screen ID</td><td>Rank</td></tr>\n")
  for screen in screenData:
    render_screen_info(out, screen)
  out.write("</table>\n")

230 231 232 233 234
  # Hotseat
  hotseat = []
  for i in range(0, HOTSEAT_SIZE):
    hotseat.append(None)
  for row in data:
235
    if row["container"] != CONTAINER_HOTSEAT:
236 237 238 239 240 241 242 243 244
      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")

245 246 247 248 249 250 251 252 253 254 255 256 257
  # 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:
    # desktop
258
    if row["container"] != CONTAINER_DESKTOP:
259
      continue
260
    screen = screens[screensIdMap.index(row["screen"])]
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
    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:
276
        render_cell_info(out, cell, occupied)
277 278 279 280 281 282 283 284 285 286 287
      out.write("</tr>\n")
    out.write("</table>\n")
    i=i+1

  out.write("""
</body>
</html>
""")

  out.close()

288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
def updateDeviceClassConstants(str):
  global SCREENS, COLUMNS, ROWS, HOTSEAT_SIZE
  devClass = str.lower()
  if devClass == "sw600":
    COLUMNS = 6
    ROWS = 6
    HOTSEAT_SIZE = 6
    return True
  elif devClass == "sw720":
    COLUMNS = 8
    ROWS = 6
    HOTSEAT_SIZE = 8
    return True
  return False

303
def main(argv):
304
  if len(argv) == 1 or (len(argv) == 2 and updateDeviceClassConstants(argv[1])):
305
    make_dir()
306
    adb_root_remount()
307 308
    pull_file(AUTO_FILE)
    process_file(AUTO_FILE)
309
  elif len(argv) == 2 or (len(argv) == 3 and updateDeviceClassConstants(argv[2])):
310 311 312 313 314 315 316
    make_dir()
    process_file(argv[1])
  else:
    usage()

if __name__=="__main__":
  main(sys.argv)