resolved conflicts for merge of 35e79e32 to gingerbread-plus-aosp
Change-Id: I039355b9d5852436c8352efc5a85590e5f2bc080
diff --git a/Android.mk b/Android.mk
index dc72ec6..5285e18 100644
--- a/Android.mk
+++ b/Android.mk
@@ -28,6 +28,6 @@
LOCAL_OVERRIDES_PACKAGES := Home
-LOCAL_PROGUARD_FLAGS := -include $(LOCAL_PATH)/proguard.flags
+LOCAL_PROGUARD_FLAG_FILES := proguard.flags
include $(BUILD_PACKAGE)
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)
diff --git a/res/drawable-hdpi/all_apps_button_focused.png b/res/drawable-hdpi/all_apps_button_focused.png
index 55574ed..ace493b 100644
--- a/res/drawable-hdpi/all_apps_button_focused.png
+++ b/res/drawable-hdpi/all_apps_button_focused.png
Binary files differ
diff --git a/res/drawable-hdpi/all_apps_button_normal.png b/res/drawable-hdpi/all_apps_button_normal.png
index 7e7ec86..cde455d 100644
--- a/res/drawable-hdpi/all_apps_button_normal.png
+++ b/res/drawable-hdpi/all_apps_button_normal.png
Binary files differ
diff --git a/res/drawable-hdpi/all_apps_button_pressed.png b/res/drawable-hdpi/all_apps_button_pressed.png
index 3ccb5af..d5f9f54 100644
--- a/res/drawable-hdpi/all_apps_button_pressed.png
+++ b/res/drawable-hdpi/all_apps_button_pressed.png
Binary files differ
diff --git a/res/drawable-hdpi/hotseat_bg_center.9.png b/res/drawable-hdpi/hotseat_bg_center.9.png
index 468e766..50a9521 100644
--- a/res/drawable-hdpi/hotseat_bg_center.9.png
+++ b/res/drawable-hdpi/hotseat_bg_center.9.png
Binary files differ
diff --git a/res/drawable-hdpi/hotseat_bg_left.9.png b/res/drawable-hdpi/hotseat_bg_left.9.png
index 433a10e..78cbaf9 100644
--- a/res/drawable-hdpi/hotseat_bg_left.9.png
+++ b/res/drawable-hdpi/hotseat_bg_left.9.png
Binary files differ
diff --git a/res/drawable-hdpi/hotseat_bg_right.9.png b/res/drawable-hdpi/hotseat_bg_right.9.png
index 4ea2a73..6cf8ead 100644
--- a/res/drawable-hdpi/hotseat_bg_right.9.png
+++ b/res/drawable-hdpi/hotseat_bg_right.9.png
Binary files differ
diff --git a/res/drawable-hdpi/hotseat_browser_focused.png b/res/drawable-hdpi/hotseat_browser_focused.png
index 6717ad2..4020a89 100644
--- a/res/drawable-hdpi/hotseat_browser_focused.png
+++ b/res/drawable-hdpi/hotseat_browser_focused.png
Binary files differ
diff --git a/res/drawable-hdpi/hotseat_browser_normal.png b/res/drawable-hdpi/hotseat_browser_normal.png
index d02fdd9..c7f902a 100644
--- a/res/drawable-hdpi/hotseat_browser_normal.png
+++ b/res/drawable-hdpi/hotseat_browser_normal.png
Binary files differ
diff --git a/res/drawable-hdpi/hotseat_browser_pressed.png b/res/drawable-hdpi/hotseat_browser_pressed.png
index 71df2d1..bfa23b3 100644
--- a/res/drawable-hdpi/hotseat_browser_pressed.png
+++ b/res/drawable-hdpi/hotseat_browser_pressed.png
Binary files differ
diff --git a/res/drawable-hdpi/hotseat_left.png b/res/drawable-hdpi/hotseat_left.png
deleted file mode 100644
index 5dabf57e..0000000
--- a/res/drawable-hdpi/hotseat_left.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/hotseat_phone_focused.png b/res/drawable-hdpi/hotseat_phone_focused.png
index 3e84a58..f81f0a8 100644
--- a/res/drawable-hdpi/hotseat_phone_focused.png
+++ b/res/drawable-hdpi/hotseat_phone_focused.png
Binary files differ
diff --git a/res/drawable-hdpi/hotseat_phone_normal.png b/res/drawable-hdpi/hotseat_phone_normal.png
index e8a869c..391802e 100644
--- a/res/drawable-hdpi/hotseat_phone_normal.png
+++ b/res/drawable-hdpi/hotseat_phone_normal.png
Binary files differ
diff --git a/res/drawable-hdpi/hotseat_phone_pressed.png b/res/drawable-hdpi/hotseat_phone_pressed.png
index dc4ad6e..a6c2baf 100644
--- a/res/drawable-hdpi/hotseat_phone_pressed.png
+++ b/res/drawable-hdpi/hotseat_phone_pressed.png
Binary files differ
diff --git a/res/drawable-hdpi/hotseat_right.png b/res/drawable-hdpi/hotseat_right.png
deleted file mode 100644
index 114bcb5..0000000
--- a/res/drawable-hdpi/hotseat_right.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/hotseat_browser_normal.png b/res/drawable-mdpi/hotseat_browser_normal.png
index 4c662fd..4a4a6e3 100644
--- a/res/drawable-mdpi/hotseat_browser_normal.png
+++ b/res/drawable-mdpi/hotseat_browser_normal.png
Binary files differ
diff --git a/res/drawable-mdpi/hotseat_phone_normal.png b/res/drawable-mdpi/hotseat_phone_normal.png
index d759b1f..7f20428 100644
--- a/res/drawable-mdpi/hotseat_phone_normal.png
+++ b/res/drawable-mdpi/hotseat_phone_normal.png
Binary files differ
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index bad2730..3c16bbb 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -46,10 +46,14 @@
<string name="shortcut_uninstalled" msgid="2129499669449749995">"Zástupce <xliff:g id="NAME">%s</xliff:g> byl odebrán."</string>
<string name="shortcut_duplicate" msgid="4757756326465060694">"Zástupce <xliff:g id="NAME">%s</xliff:g> již existuje."</string>
<string name="title_select_shortcut" msgid="2858897527672831763">"Vyberte zástupce"</string>
+ <!-- no translation found for title_select_application (8031072293115454221) -->
+ <skip />
<string name="title_select_live_folder" msgid="3753447798805166749">"Vybrat složku"</string>
<string name="all_apps_button_label" msgid="3953036962111614813">"Všechny aplikace"</string>
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Plocha"</string>
<string name="menu_add" msgid="3065046628354640854">"Přidat"</string>
+ <!-- no translation found for menu_manage_apps (2864265778240958621) -->
+ <skip />
<string name="menu_wallpaper" msgid="5837429080911269832">"Tapeta"</string>
<string name="menu_search" msgid="4826514464423239041">"Hledat"</string>
<string name="menu_notifications" msgid="6424587053194766192">"Oznámení"</string>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 6ec1516..9c36d73 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -46,10 +46,14 @@
<string name="shortcut_uninstalled" msgid="2129499669449749995">"Genvejen \"<xliff:g id="NAME">%s</xliff:g>\" blev fjernet."</string>
<string name="shortcut_duplicate" msgid="4757756326465060694">"Genvejen \"<xliff:g id="NAME">%s</xliff:g>\" findes allerede."</string>
<string name="title_select_shortcut" msgid="2858897527672831763">"Vælg genvej"</string>
+ <!-- no translation found for title_select_application (8031072293115454221) -->
+ <skip />
<string name="title_select_live_folder" msgid="3753447798805166749">"Vælg mappe"</string>
<string name="all_apps_button_label" msgid="3953036962111614813">"Alle programmer"</string>
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Start"</string>
<string name="menu_add" msgid="3065046628354640854">"Tilføj"</string>
+ <!-- no translation found for menu_manage_apps (2864265778240958621) -->
+ <skip />
<string name="menu_wallpaper" msgid="5837429080911269832">"Tapet"</string>
<string name="menu_search" msgid="4826514464423239041">"Søg"</string>
<string name="menu_notifications" msgid="6424587053194766192">"Meddelelser"</string>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index e4f705e..b3c85c7 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -46,10 +46,14 @@
<string name="shortcut_uninstalled" msgid="2129499669449749995">"\"<xliff:g id="NAME">%s</xliff:g>\"-Verknüpfung wurde entfernt."</string>
<string name="shortcut_duplicate" msgid="4757756326465060694">"\"<xliff:g id="NAME">%s</xliff:g>\"-Verknüpfung ist bereits vorhanden."</string>
<string name="title_select_shortcut" msgid="2858897527672831763">"Tastenkürzel auswählen"</string>
+ <!-- no translation found for title_select_application (8031072293115454221) -->
+ <skip />
<string name="title_select_live_folder" msgid="3753447798805166749">"Ordner auswählen"</string>
<string name="all_apps_button_label" msgid="3953036962111614813">"Alle Anwendungen"</string>
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Startseite"</string>
<string name="menu_add" msgid="3065046628354640854">"Hinzufügen"</string>
+ <!-- no translation found for menu_manage_apps (2864265778240958621) -->
+ <skip />
<string name="menu_wallpaper" msgid="5837429080911269832">"Hintergrund"</string>
<string name="menu_search" msgid="4826514464423239041">"Suchen"</string>
<string name="menu_notifications" msgid="6424587053194766192">"Benachrichtigungen"</string>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 6514964..a0b3e7a 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -46,10 +46,14 @@
<string name="shortcut_uninstalled" msgid="2129499669449749995">"Η συντόμευση \"<xliff:g id="NAME">%s</xliff:g>\" καταργήθηκε."</string>
<string name="shortcut_duplicate" msgid="4757756326465060694">"Η συντόμευση \"<xliff:g id="NAME">%s</xliff:g>\" υπάρχει ήδη."</string>
<string name="title_select_shortcut" msgid="2858897527672831763">"Επιλογή συντόμευσης"</string>
+ <!-- no translation found for title_select_application (8031072293115454221) -->
+ <skip />
<string name="title_select_live_folder" msgid="3753447798805166749">"Επιλογή φακέλου"</string>
<string name="all_apps_button_label" msgid="3953036962111614813">"Όλες οι εφαρμογές"</string>
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Αρχική σελίδα"</string>
<string name="menu_add" msgid="3065046628354640854">"Προσθήκη"</string>
+ <!-- no translation found for menu_manage_apps (2864265778240958621) -->
+ <skip />
<string name="menu_wallpaper" msgid="5837429080911269832">"Ταπετσαρία"</string>
<string name="menu_search" msgid="4826514464423239041">"Αναζήτηση"</string>
<string name="menu_notifications" msgid="6424587053194766192">"Ειδοποιήσεις"</string>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 5f6b4e5..79fc72d 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -46,10 +46,14 @@
<string name="shortcut_uninstalled" msgid="2129499669449749995">"El acceso directo \"<xliff:g id="NAME">%s</xliff:g>\" ha sido eliminado."</string>
<string name="shortcut_duplicate" msgid="4757756326465060694">"El acceso directo \"<xliff:g id="NAME">%s</xliff:g>\" ya existe."</string>
<string name="title_select_shortcut" msgid="2858897527672831763">"Seleccionar acceso directo"</string>
+ <!-- no translation found for title_select_application (8031072293115454221) -->
+ <skip />
<string name="title_select_live_folder" msgid="3753447798805166749">"Seleccionar carpeta"</string>
<string name="all_apps_button_label" msgid="3953036962111614813">"Todas las aplicaciones"</string>
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Página principal"</string>
<string name="menu_add" msgid="3065046628354640854">"Agregar"</string>
+ <!-- no translation found for menu_manage_apps (2864265778240958621) -->
+ <skip />
<string name="menu_wallpaper" msgid="5837429080911269832">"Papel tapiz"</string>
<string name="menu_search" msgid="4826514464423239041">"Buscar"</string>
<string name="menu_notifications" msgid="6424587053194766192">"Notificaciones"</string>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 5b46c59..4fd5c3d 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -46,10 +46,14 @@
<string name="shortcut_uninstalled" msgid="2129499669449749995">"Se ha eliminado el acceso directo \"<xliff:g id="NAME">%s</xliff:g>\"."</string>
<string name="shortcut_duplicate" msgid="4757756326465060694">"El acceso directo \"<xliff:g id="NAME">%s</xliff:g>\" ya existe."</string>
<string name="title_select_shortcut" msgid="2858897527672831763">"Seleccionar acceso directo"</string>
+ <!-- no translation found for title_select_application (8031072293115454221) -->
+ <skip />
<string name="title_select_live_folder" msgid="3753447798805166749">"Seleccionar carpeta"</string>
<string name="all_apps_button_label" msgid="3953036962111614813">"Todas las aplicaciones"</string>
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Inicio"</string>
<string name="menu_add" msgid="3065046628354640854">"Añadir"</string>
+ <!-- no translation found for menu_manage_apps (2864265778240958621) -->
+ <skip />
<string name="menu_wallpaper" msgid="5837429080911269832">"Fondo de pantalla"</string>
<string name="menu_search" msgid="4826514464423239041">"Buscar con Google"</string>
<string name="menu_notifications" msgid="6424587053194766192">"Notificaciones"</string>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index f1fb440..1799377 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -46,10 +46,14 @@
<string name="shortcut_uninstalled" msgid="2129499669449749995">"Le raccourci \"<xliff:g id="NAME">%s</xliff:g>\" a été supprimé."</string>
<string name="shortcut_duplicate" msgid="4757756326465060694">"Le raccourci \"<xliff:g id="NAME">%s</xliff:g>\" existe déjà."</string>
<string name="title_select_shortcut" msgid="2858897527672831763">"Sélectionner un raccourci"</string>
+ <!-- no translation found for title_select_application (8031072293115454221) -->
+ <skip />
<string name="title_select_live_folder" msgid="3753447798805166749">"Sélectionner le dossier"</string>
<string name="all_apps_button_label" msgid="3953036962111614813">"Toutes les applications"</string>
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Page d\'accueil"</string>
<string name="menu_add" msgid="3065046628354640854">"Ajouter"</string>
+ <!-- no translation found for menu_manage_apps (2864265778240958621) -->
+ <skip />
<string name="menu_wallpaper" msgid="5837429080911269832">"Fond d\'écran"</string>
<string name="menu_search" msgid="4826514464423239041">"Rechercher"</string>
<string name="menu_notifications" msgid="6424587053194766192">"Notifications"</string>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 950e15f..62e91b5 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -46,16 +46,20 @@
<string name="shortcut_uninstalled" msgid="2129499669449749995">"La scorciatoia \"<xliff:g id="NAME">%s</xliff:g>\" è stata rimossa."</string>
<string name="shortcut_duplicate" msgid="4757756326465060694">"Scorciatoia \"<xliff:g id="NAME">%s</xliff:g>\" già presente."</string>
<string name="title_select_shortcut" msgid="2858897527672831763">"Seleziona scorciatoia"</string>
+ <!-- no translation found for title_select_application (8031072293115454221) -->
+ <skip />
<string name="title_select_live_folder" msgid="3753447798805166749">"Seleziona cartella"</string>
<string name="all_apps_button_label" msgid="3953036962111614813">"Tutte le applicazioni"</string>
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Home"</string>
<string name="menu_add" msgid="3065046628354640854">"Aggiungi"</string>
+ <!-- no translation found for menu_manage_apps (2864265778240958621) -->
+ <skip />
<string name="menu_wallpaper" msgid="5837429080911269832">"Sfondo"</string>
<string name="menu_search" msgid="4826514464423239041">"Cerca"</string>
<string name="menu_notifications" msgid="6424587053194766192">"Notifiche"</string>
<string name="menu_gestures" msgid="514678675575912237">"Gesti"</string>
<string name="menu_settings" msgid="6233960148378443661">"Impostazioni"</string>
- <string name="permlab_install_shortcut" msgid="1201690825493376489">"aggiungere scorciatorie"</string>
+ <string name="permlab_install_shortcut" msgid="1201690825493376489">"aggiungere scorciatoie"</string>
<string name="permdesc_install_shortcut" msgid="7429365847558984148">"Consente a un\'applicazione di aggiungere scorciatoie automaticamente."</string>
<string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"eliminare scorciatoie"</string>
<string name="permdesc_uninstall_shortcut" msgid="959972195916090900">"Consente a un\'applicazione di rimuovere scorciatoie automaticamente."</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 021b895..6b09d00 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -46,10 +46,14 @@
<string name="shortcut_uninstalled" msgid="2129499669449749995">"ショートカット「<xliff:g id="NAME">%s</xliff:g>」を削除しました。"</string>
<string name="shortcut_duplicate" msgid="4757756326465060694">"ショートカット「<xliff:g id="NAME">%s</xliff:g>」は既に存在します。"</string>
<string name="title_select_shortcut" msgid="2858897527672831763">"ショートカットを選択"</string>
+ <!-- no translation found for title_select_application (8031072293115454221) -->
+ <skip />
<string name="title_select_live_folder" msgid="3753447798805166749">"フォルダの選択"</string>
<string name="all_apps_button_label" msgid="3953036962111614813">"すべてのアプリケーション"</string>
<string name="all_apps_home_button_label" msgid="1022222300329398558">"ホーム"</string>
<string name="menu_add" msgid="3065046628354640854">"追加"</string>
+ <!-- no translation found for menu_manage_apps (2864265778240958621) -->
+ <skip />
<string name="menu_wallpaper" msgid="5837429080911269832">"壁紙"</string>
<string name="menu_search" msgid="4826514464423239041">"検索"</string>
<string name="menu_notifications" msgid="6424587053194766192">"通知"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 341c7ee..db32a02 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -46,10 +46,14 @@
<string name="shortcut_uninstalled" msgid="2129499669449749995">"바로가기(\'<xliff:g id="NAME">%s</xliff:g>\')가 삭제되었습니다."</string>
<string name="shortcut_duplicate" msgid="4757756326465060694">"바로가기(\'<xliff:g id="NAME">%s</xliff:g>\')가 이미 있습니다."</string>
<string name="title_select_shortcut" msgid="2858897527672831763">"바로가기 선택"</string>
+ <!-- no translation found for title_select_application (8031072293115454221) -->
+ <skip />
<string name="title_select_live_folder" msgid="3753447798805166749">"폴더 선택"</string>
<string name="all_apps_button_label" msgid="3953036962111614813">"모든 애플리케이션"</string>
<string name="all_apps_home_button_label" msgid="1022222300329398558">"홈"</string>
<string name="menu_add" msgid="3065046628354640854">"추가"</string>
+ <!-- no translation found for menu_manage_apps (2864265778240958621) -->
+ <skip />
<string name="menu_wallpaper" msgid="5837429080911269832">"배경화면"</string>
<string name="menu_search" msgid="4826514464423239041">"검색"</string>
<string name="menu_notifications" msgid="6424587053194766192">"알림"</string>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 54418e1..4510fe9 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -46,10 +46,14 @@
<string name="shortcut_uninstalled" msgid="2129499669449749995">"Fjernet snarveien «<xliff:g id="NAME">%s</xliff:g>»."</string>
<string name="shortcut_duplicate" msgid="4757756326465060694">"Snarveien «<xliff:g id="NAME">%s</xliff:g>» fins allerede."</string>
<string name="title_select_shortcut" msgid="2858897527672831763">"Velg snarvei"</string>
+ <!-- no translation found for title_select_application (8031072293115454221) -->
+ <skip />
<string name="title_select_live_folder" msgid="3753447798805166749">"Velg mappe"</string>
<string name="all_apps_button_label" msgid="3953036962111614813">"Alle programmer"</string>
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Startsiden"</string>
<string name="menu_add" msgid="3065046628354640854">"Legg til"</string>
+ <!-- no translation found for menu_manage_apps (2864265778240958621) -->
+ <skip />
<string name="menu_wallpaper" msgid="5837429080911269832">"Bakgrunnsbilde"</string>
<string name="menu_search" msgid="4826514464423239041">"Søk"</string>
<string name="menu_notifications" msgid="6424587053194766192">"Varslinger"</string>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index f5ac90e..6caae8b 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -46,10 +46,14 @@
<string name="shortcut_uninstalled" msgid="2129499669449749995">"Snelkoppeling \'<xliff:g id="NAME">%s</xliff:g>\' is verwijderd."</string>
<string name="shortcut_duplicate" msgid="4757756326465060694">"Snelkoppeling \'<xliff:g id="NAME">%s</xliff:g>\' bestaat al."</string>
<string name="title_select_shortcut" msgid="2858897527672831763">"Snelkoppeling selecteren"</string>
+ <!-- no translation found for title_select_application (8031072293115454221) -->
+ <skip />
<string name="title_select_live_folder" msgid="3753447798805166749">"Map selecteren"</string>
<string name="all_apps_button_label" msgid="3953036962111614813">"Alle toepassingen"</string>
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Startpagina"</string>
<string name="menu_add" msgid="3065046628354640854">"Toevoegen"</string>
+ <!-- no translation found for menu_manage_apps (2864265778240958621) -->
+ <skip />
<string name="menu_wallpaper" msgid="5837429080911269832">"Achtergrond"</string>
<string name="menu_search" msgid="4826514464423239041">"Zoeken"</string>
<string name="menu_notifications" msgid="6424587053194766192">"Meldingen"</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index d50a59a..0d8e351 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -46,10 +46,14 @@
<string name="shortcut_uninstalled" msgid="2129499669449749995">"Skrót „<xliff:g id="NAME">%s</xliff:g>” został usunięty."</string>
<string name="shortcut_duplicate" msgid="4757756326465060694">"Skrót „<xliff:g id="NAME">%s</xliff:g>” już istnieje."</string>
<string name="title_select_shortcut" msgid="2858897527672831763">"Wybierz skrót"</string>
+ <!-- no translation found for title_select_application (8031072293115454221) -->
+ <skip />
<string name="title_select_live_folder" msgid="3753447798805166749">"Wybierz folder"</string>
<string name="all_apps_button_label" msgid="3953036962111614813">"Wszystkie aplikacje"</string>
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Ekran główny"</string>
<string name="menu_add" msgid="3065046628354640854">"Dodaj"</string>
+ <!-- no translation found for menu_manage_apps (2864265778240958621) -->
+ <skip />
<string name="menu_wallpaper" msgid="5837429080911269832">"Tapeta"</string>
<string name="menu_search" msgid="4826514464423239041">"Szukaj"</string>
<string name="menu_notifications" msgid="6424587053194766192">"Powiadomienia"</string>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index df63f30..824d18a 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -46,10 +46,14 @@
<string name="shortcut_uninstalled" msgid="2129499669449749995">"O atalho \"<xliff:g id="NAME">%s</xliff:g>\" foi removido."</string>
<string name="shortcut_duplicate" msgid="4757756326465060694">"O atalho \"<xliff:g id="NAME">%s</xliff:g>\" já existe."</string>
<string name="title_select_shortcut" msgid="2858897527672831763">"Seleccione o atalho"</string>
+ <!-- no translation found for title_select_application (8031072293115454221) -->
+ <skip />
<string name="title_select_live_folder" msgid="3753447798805166749">"Seleccione a pasta"</string>
<string name="all_apps_button_label" msgid="3953036962111614813">"Todas as aplicações"</string>
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Página inicial"</string>
<string name="menu_add" msgid="3065046628354640854">"Adicionar"</string>
+ <!-- no translation found for menu_manage_apps (2864265778240958621) -->
+ <skip />
<string name="menu_wallpaper" msgid="5837429080911269832">"Imagem de fundo"</string>
<string name="menu_search" msgid="4826514464423239041">"Pesquisar"</string>
<string name="menu_notifications" msgid="6424587053194766192">"Notificações"</string>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index b72f7e0..dc6441d 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -46,10 +46,14 @@
<string name="shortcut_uninstalled" msgid="2129499669449749995">"O atalho \"<xliff:g id="NAME">%s</xliff:g>\" foi removido."</string>
<string name="shortcut_duplicate" msgid="4757756326465060694">"O atalho \"<xliff:g id="NAME">%s</xliff:g>\" já existe."</string>
<string name="title_select_shortcut" msgid="2858897527672831763">"Selecionar atalho"</string>
+ <!-- no translation found for title_select_application (8031072293115454221) -->
+ <skip />
<string name="title_select_live_folder" msgid="3753447798805166749">"Selecionar pasta"</string>
<string name="all_apps_button_label" msgid="3953036962111614813">"Todos os aplicativos"</string>
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Página inicial"</string>
<string name="menu_add" msgid="3065046628354640854">"Adicionar"</string>
+ <!-- no translation found for menu_manage_apps (2864265778240958621) -->
+ <skip />
<string name="menu_wallpaper" msgid="5837429080911269832">"Plano de fundo"</string>
<string name="menu_search" msgid="4826514464423239041">"Pesquisa"</string>
<string name="menu_notifications" msgid="6424587053194766192">"Notificações"</string>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index b151618..2454b58 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -46,10 +46,14 @@
<string name="shortcut_uninstalled" msgid="2129499669449749995">"Ярлык \"<xliff:g id="NAME">%s</xliff:g>\" удален."</string>
<string name="shortcut_duplicate" msgid="4757756326465060694">"Ярлык \"<xliff:g id="NAME">%s</xliff:g>\" уже существует."</string>
<string name="title_select_shortcut" msgid="2858897527672831763">"Выберите ярлык"</string>
+ <!-- no translation found for title_select_application (8031072293115454221) -->
+ <skip />
<string name="title_select_live_folder" msgid="3753447798805166749">"Выбор папки"</string>
<string name="all_apps_button_label" msgid="3953036962111614813">"Все приложения"</string>
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Главная"</string>
<string name="menu_add" msgid="3065046628354640854">"Добавить"</string>
+ <!-- no translation found for menu_manage_apps (2864265778240958621) -->
+ <skip />
<string name="menu_wallpaper" msgid="5837429080911269832">"Обои"</string>
<string name="menu_search" msgid="4826514464423239041">"Поиск"</string>
<string name="menu_notifications" msgid="6424587053194766192">"Уведомления"</string>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 9c29ef1..cf44973 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -46,10 +46,14 @@
<string name="shortcut_uninstalled" msgid="2129499669449749995">"Genvägen \"<xliff:g id="NAME">%s</xliff:g>\" har tagits bort."</string>
<string name="shortcut_duplicate" msgid="4757756326465060694">"Genvägen \"<xliff:g id="NAME">%s</xliff:g>\" finns redan."</string>
<string name="title_select_shortcut" msgid="2858897527672831763">"Välj genväg"</string>
+ <!-- no translation found for title_select_application (8031072293115454221) -->
+ <skip />
<string name="title_select_live_folder" msgid="3753447798805166749">"Välj mapp"</string>
<string name="all_apps_button_label" msgid="3953036962111614813">"Alla program"</string>
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Startsida"</string>
<string name="menu_add" msgid="3065046628354640854">"Lägg till"</string>
+ <!-- no translation found for menu_manage_apps (2864265778240958621) -->
+ <skip />
<string name="menu_wallpaper" msgid="5837429080911269832">"Bakgrund"</string>
<string name="menu_search" msgid="4826514464423239041">"Sök"</string>
<string name="menu_notifications" msgid="6424587053194766192">"Aviseringar"</string>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 43f7520..0e38092 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -46,10 +46,14 @@
<string name="shortcut_uninstalled" msgid="2129499669449749995">"\"<xliff:g id="NAME">%s</xliff:g>\" kısayolu kaldırıldı."</string>
<string name="shortcut_duplicate" msgid="4757756326465060694">"\"<xliff:g id="NAME">%s</xliff:g>\" kısayolu zaten var."</string>
<string name="title_select_shortcut" msgid="2858897527672831763">"Kısayolu seçin"</string>
+ <!-- no translation found for title_select_application (8031072293115454221) -->
+ <skip />
<string name="title_select_live_folder" msgid="3753447798805166749">"Klasörü seçin"</string>
<string name="all_apps_button_label" msgid="3953036962111614813">"Tüm uygulamalar"</string>
<string name="all_apps_home_button_label" msgid="1022222300329398558">"Ana Sayfa"</string>
<string name="menu_add" msgid="3065046628354640854">"Ekle"</string>
+ <!-- no translation found for menu_manage_apps (2864265778240958621) -->
+ <skip />
<string name="menu_wallpaper" msgid="5837429080911269832">"Duvar Kağıdı"</string>
<string name="menu_search" msgid="4826514464423239041">"Ara"</string>
<string name="menu_notifications" msgid="6424587053194766192">"Bildirimler"</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 0705787..5b69a8c 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -46,10 +46,14 @@
<string name="shortcut_uninstalled" msgid="2129499669449749995">"已删除“<xliff:g id="NAME">%s</xliff:g>”快捷方式。"</string>
<string name="shortcut_duplicate" msgid="4757756326465060694">"“<xliff:g id="NAME">%s</xliff:g>”快捷方式已存在。"</string>
<string name="title_select_shortcut" msgid="2858897527672831763">"选择快捷方式"</string>
+ <!-- no translation found for title_select_application (8031072293115454221) -->
+ <skip />
<string name="title_select_live_folder" msgid="3753447798805166749">"选择文件夹"</string>
<string name="all_apps_button_label" msgid="3953036962111614813">"所有应用程序"</string>
<string name="all_apps_home_button_label" msgid="1022222300329398558">"主屏幕"</string>
<string name="menu_add" msgid="3065046628354640854">"添加"</string>
+ <!-- no translation found for menu_manage_apps (2864265778240958621) -->
+ <skip />
<string name="menu_wallpaper" msgid="5837429080911269832">"壁纸"</string>
<string name="menu_search" msgid="4826514464423239041">"搜索"</string>
<string name="menu_notifications" msgid="6424587053194766192">"通知"</string>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index de37e19..3068335 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -46,10 +46,14 @@
<string name="shortcut_uninstalled" msgid="2129499669449749995">"已移除「<xliff:g id="NAME">%s</xliff:g>」捷徑。"</string>
<string name="shortcut_duplicate" msgid="4757756326465060694">"「<xliff:g id="NAME">%s</xliff:g>」捷徑已經存在。"</string>
<string name="title_select_shortcut" msgid="2858897527672831763">"選取捷徑"</string>
+ <!-- no translation found for title_select_application (8031072293115454221) -->
+ <skip />
<string name="title_select_live_folder" msgid="3753447798805166749">"選取資料夾"</string>
<string name="all_apps_button_label" msgid="3953036962111614813">"所有應用程式"</string>
<string name="all_apps_home_button_label" msgid="1022222300329398558">"主螢幕"</string>
<string name="menu_add" msgid="3065046628354640854">"新增"</string>
+ <!-- no translation found for menu_manage_apps (2864265778240958621) -->
+ <skip />
<string name="menu_wallpaper" msgid="5837429080911269832">"桌布"</string>
<string name="menu_search" msgid="4826514464423239041">"搜尋"</string>
<string name="menu_notifications" msgid="6424587053194766192">"通知"</string>
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 1fcabb2..6bd16ed 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="hotseats" translatable="false">
- <item>intent:#Intent;action=android.intent.action.MAIN;component=com.android.contacts/.ContactsLaunchActivity;end</item>
+ <item>intent:#Intent;action=android.intent.action.DIAL;end</item>
<item>*BROWSER*</item>
</string-array>
<array name="hotseat_icons" translatable="false">
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 790f835..c83986b 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -37,4 +37,8 @@
<!-- delete_zone_size_full - button_bar_height_portrait -->
<dimen name="delete_zone_padding">14dip</dimen>
+
+ <!-- the area at the edge of the screen that makes the workspace go left
+ or right while you're dragging. -->
+ <dimen name="scroll_zone">20dp</dimen>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 86c1b3c..bae50e4 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -88,6 +88,8 @@
<!-- Title of dialog when user is selecting shortcut to add to homescreen -->
<string name="title_select_shortcut">Select shortcut</string>
+ <!-- Title of dialog when user is selecting an application to add to homescreen -->
+ <string name="title_select_application">Select application</string>
<!-- Title of dialog when user is selecting live folder to add to homescreen -->
<string name="title_select_live_folder">Select folder</string>
@@ -101,6 +103,8 @@
<skip />
<!-- Verb, menu item used to add an item on the desktop -->
<string name="menu_add">Add</string>
+ <!-- Menu item used to manage installed applications -->
+ <string name="menu_manage_apps">Manage Apps</string>
<!-- Noun, menu item used to set the desktop's wallpaper -->
<string name="menu_wallpaper">Wallpaper</string>
<!-- Verb, menu item used to initiate global search -->
diff --git a/src/com/android/launcher2/AllApps3D.java b/src/com/android/launcher2/AllApps3D.java
index b8aa8ec..308ad28 100644
--- a/src/com/android/launcher2/AllApps3D.java
+++ b/src/com/android/launcher2/AllApps3D.java
@@ -726,7 +726,12 @@
}
public boolean onLongClick(View v) {
- if (mLocks != 0 || !isVisible()) {
+ // We don't accept long click events in these cases
+ // - If the workspace isn't ready to accept a drop
+ // - If we're not done loading (because we might be confused about which item
+ // to pick up
+ // - If we're not visible
+ if (!isVisible() || mLauncher.isWorkspaceLocked() || mLocks != 0) {
return true;
}
if (sRollo.checkClickOK() && mCurrentIconIndex == mDownIconIndex
diff --git a/src/com/android/launcher2/AllAppsList.java b/src/com/android/launcher2/AllAppsList.java
index 41aa6ca..3a5baea 100644
--- a/src/com/android/launcher2/AllAppsList.java
+++ b/src/com/android/launcher2/AllAppsList.java
@@ -150,6 +150,17 @@
modified.add(applicationInfo);
}
}
+ } else {
+ // Remove all data for this package.
+ for (int i = data.size() - 1; i >= 0; i--) {
+ final ApplicationInfo applicationInfo = data.get(i);
+ final ComponentName component = applicationInfo.intent.getComponent();
+ if (packageName.equals(component.getPackageName())) {
+ removed.add(applicationInfo);
+ mIconCache.remove(component);
+ data.remove(i);
+ }
+ }
}
}
@@ -161,23 +172,10 @@
final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+ mainIntent.setPackage(packageName);
final List<ResolveInfo> apps = packageManager.queryIntentActivities(mainIntent, 0);
- final List<ResolveInfo> matches = new ArrayList<ResolveInfo>();
-
- if (apps != null) {
- // Find all activities that match the packageName
- int count = apps.size();
- for (int i = 0; i < count; i++) {
- final ResolveInfo info = apps.get(i);
- final ActivityInfo activityInfo = info.activityInfo;
- if (packageName.equals(activityInfo.packageName)) {
- matches.add(info);
- }
- }
- }
-
- return matches;
+ return apps != null ? apps : new ArrayList<ResolveInfo>();
}
/**
diff --git a/src/com/android/launcher2/DeleteZone.java b/src/com/android/launcher2/DeleteZone.java
index 3a6c63d..4e8b204 100644
--- a/src/com/android/launcher2/DeleteZone.java
+++ b/src/com/android/launcher2/DeleteZone.java
@@ -116,7 +116,14 @@
final LauncherAppWidgetInfo launcherAppWidgetInfo = (LauncherAppWidgetInfo) item;
final LauncherAppWidgetHost appWidgetHost = mLauncher.getAppWidgetHost();
if (appWidgetHost != null) {
- appWidgetHost.deleteAppWidgetId(launcherAppWidgetInfo.appWidgetId);
+ final int appWidgetId = launcherAppWidgetInfo.appWidgetId;
+ // Deleting an app widget ID is a void call but writes to disk before returning
+ // to the caller...
+ new Thread("deleteAppWidgetId") {
+ public void run() {
+ appWidgetHost.deleteAppWidgetId(launcherAppWidgetInfo.appWidgetId);
+ }
+ }.start();
}
}
LauncherModel.deleteItemFromDatabase(mLauncher, item);
diff --git a/src/com/android/launcher2/DragController.java b/src/com/android/launcher2/DragController.java
index b4f972b..b453061 100644
--- a/src/com/android/launcher2/DragController.java
+++ b/src/com/android/launcher2/DragController.java
@@ -33,6 +33,8 @@
import java.util.ArrayList;
+import com.android.launcher.R;
+
/**
* Class for initiating a drag within a view or across multiple views.
*/
@@ -47,7 +49,6 @@
public static int DRAG_ACTION_COPY = 1;
private static final int SCROLL_DELAY = 600;
- private static final int SCROLL_ZONE = 20;
private static final int VIBRATE_DURATION = 35;
private static final boolean PROFILE_DRAWING_DURING_DRAG = false;
@@ -87,6 +88,11 @@
/** Y offset from the upper-left corner of the cell to where we touched. */
private float mTouchOffsetY;
+ /** the area at the edge of the screen that makes the workspace go left
+ * or right while you're dragging.
+ */
+ private int mScrollZone;
+
/** Where the drag originated */
private DragSource mDragSource;
@@ -147,6 +153,7 @@
public DragController(Context context) {
mContext = context;
mHandler = new Handler();
+ mScrollZone = context.getResources().getDimensionPixelSize(R.dimen.scroll_zone);
}
/**
@@ -378,7 +385,7 @@
mMotionDownX = screenX;
mMotionDownY = screenY;
- if ((screenX < SCROLL_ZONE) || (screenX > scrollView.getWidth() - SCROLL_ZONE)) {
+ if ((screenX < mScrollZone) || (screenX > scrollView.getWidth() - mScrollZone)) {
mScrollState = SCROLL_WAITING_IN_ZONE;
mHandler.postDelayed(mScrollRunnable, SCROLL_DELAY);
} else {
@@ -419,13 +426,15 @@
if (mDeleteRegion != null) {
inDeleteRegion = mDeleteRegion.contains(screenX, screenY);
}
- if (!inDeleteRegion && screenX < SCROLL_ZONE) {
+ //Log.d(Launcher.TAG, "inDeleteRegion=" + inDeleteRegion + " screenX=" + screenX
+ // + " mScrollZone=" + mScrollZone);
+ if (!inDeleteRegion && screenX < mScrollZone) {
if (mScrollState == SCROLL_OUTSIDE_ZONE) {
mScrollState = SCROLL_WAITING_IN_ZONE;
mScrollRunnable.setDirection(SCROLL_LEFT);
mHandler.postDelayed(mScrollRunnable, SCROLL_DELAY);
}
- } else if (!inDeleteRegion && screenX > scrollView.getWidth() - SCROLL_ZONE) {
+ } else if (!inDeleteRegion && screenX > scrollView.getWidth() - mScrollZone) {
if (mScrollState == SCROLL_OUTSIDE_ZONE) {
mScrollState = SCROLL_WAITING_IN_ZONE;
mScrollRunnable.setDirection(SCROLL_RIGHT);
diff --git a/src/com/android/launcher2/IconCache.java b/src/com/android/launcher2/IconCache.java
index 4bb7d08..81a786c 100644
--- a/src/com/android/launcher2/IconCache.java
+++ b/src/com/android/launcher2/IconCache.java
@@ -124,6 +124,10 @@
}
}
+ public boolean isDefaultIcon(Bitmap icon) {
+ return mDefaultIcon == icon;
+ }
+
private CacheEntry cacheLocked(ComponentName componentName, ResolveInfo info) {
CacheEntry entry = mCache.get(componentName);
if (entry == null) {
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 2742f2f..96934e8 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -46,6 +46,7 @@
import android.graphics.drawable.Drawable;
import android.graphics.drawable.ColorDrawable;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
@@ -105,7 +106,8 @@
private static final int MENU_GROUP_WALLPAPER = MENU_GROUP_ADD + 1;
private static final int MENU_ADD = Menu.FIRST + 1;
- private static final int MENU_WALLPAPER_SETTINGS = MENU_ADD + 1;
+ private static final int MENU_MANAGE_APPS = MENU_ADD + 1;
+ private static final int MENU_WALLPAPER_SETTINGS = MENU_MANAGE_APPS + 1;
private static final int MENU_SEARCH = MENU_WALLPAPER_SETTINGS + 1;
private static final int MENU_NOTIFICATIONS = MENU_SEARCH + 1;
private static final int MENU_SETTINGS = MENU_NOTIFICATIONS + 1;
@@ -199,8 +201,10 @@
private LauncherModel mModel;
private IconCache mIconCache;
+ private static LocaleConfiguration sLocaleConfiguration = null;
+
private ArrayList<ItemInfo> mDesktopItems = new ArrayList<ItemInfo>();
- private static HashMap<Long, FolderInfo> mFolders = new HashMap<Long, FolderInfo>();
+ private static HashMap<Long, FolderInfo> sFolders = new HashMap<Long, FolderInfo>();
private ImageView mPreviousView;
private ImageView mNextView;
@@ -262,31 +266,51 @@
}
private void checkForLocaleChange() {
- final LocaleConfiguration localeConfiguration = new LocaleConfiguration();
- readConfiguration(this, localeConfiguration);
+ if (sLocaleConfiguration == null) {
+ new AsyncTask<Void, Void, LocaleConfiguration>() {
+ @Override
+ protected LocaleConfiguration doInBackground(Void... unused) {
+ LocaleConfiguration localeConfiguration = new LocaleConfiguration();
+ readConfiguration(Launcher.this, localeConfiguration);
+ return localeConfiguration;
+ }
+
+ @Override
+ protected void onPostExecute(LocaleConfiguration result) {
+ sLocaleConfiguration = result;
+ checkForLocaleChange(); // recursive, but now with a locale configuration
+ }
+ }.execute();
+ return;
+ }
final Configuration configuration = getResources().getConfiguration();
- final String previousLocale = localeConfiguration.locale;
+ final String previousLocale = sLocaleConfiguration.locale;
final String locale = configuration.locale.toString();
- final int previousMcc = localeConfiguration.mcc;
+ final int previousMcc = sLocaleConfiguration.mcc;
final int mcc = configuration.mcc;
- final int previousMnc = localeConfiguration.mnc;
+ final int previousMnc = sLocaleConfiguration.mnc;
final int mnc = configuration.mnc;
boolean localeChanged = !locale.equals(previousLocale) || mcc != previousMcc || mnc != previousMnc;
if (localeChanged) {
- localeConfiguration.locale = locale;
- localeConfiguration.mcc = mcc;
- localeConfiguration.mnc = mnc;
+ sLocaleConfiguration.locale = locale;
+ sLocaleConfiguration.mcc = mcc;
+ sLocaleConfiguration.mnc = mnc;
- writeConfiguration(this, localeConfiguration);
mIconCache.flush();
-
loadHotseats();
+
+ final LocaleConfiguration localeConfiguration = sLocaleConfiguration;
+ new Thread("WriteLocaleConfiguration") {
+ public void run() {
+ writeConfiguration(Launcher.this, localeConfiguration);
+ }
+ }.start();
}
}
@@ -689,7 +713,7 @@
boolean renameFolder = savedState.getBoolean(RUNTIME_STATE_PENDING_FOLDER_RENAME, false);
if (renameFolder) {
long id = savedState.getLong(RUNTIME_STATE_PENDING_FOLDER_RENAME_ID);
- mFolderInfo = mModel.getFolderById(this, mFolders, id);
+ mFolderInfo = mModel.getFolderById(this, sFolders, id);
mRestoring = true;
}
}
@@ -1088,6 +1112,9 @@
menu.add(MENU_GROUP_ADD, MENU_ADD, 0, R.string.menu_add)
.setIcon(android.R.drawable.ic_menu_add)
.setAlphabeticShortcut('A');
+ menu.add(0, MENU_MANAGE_APPS, 0, R.string.menu_manage_apps)
+ .setIcon(android.R.drawable.ic_menu_manage)
+ .setAlphabeticShortcut('M');
menu.add(MENU_GROUP_WALLPAPER, MENU_WALLPAPER_SETTINGS, 0, R.string.menu_wallpaper)
.setIcon(android.R.drawable.ic_menu_gallery)
.setAlphabeticShortcut('W');
@@ -1139,6 +1166,9 @@
case MENU_ADD:
addItems();
return true;
+ case MENU_MANAGE_APPS:
+ manageApps();
+ return true;
case MENU_WALLPAPER_SETTINGS:
startWallpaper();
return true;
@@ -1173,6 +1203,10 @@
showAddDialog(mMenuAddInfo);
}
+ private void manageApps() {
+ startActivity(new Intent(android.provider.Settings.ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS));
+ }
+
void addAppWidget(Intent data) {
// TODO: catch bad widget exception when sent
int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
@@ -1202,9 +1236,10 @@
Intent pickIntent = new Intent(Intent.ACTION_PICK_ACTIVITY);
pickIntent.putExtra(Intent.EXTRA_INTENT, mainIntent);
- startActivityForResult(pickIntent, REQUEST_PICK_APPLICATION);
+ pickIntent.putExtra(Intent.EXTRA_TITLE, getText(R.string.title_select_application));
+ startActivityForResultSafely(pickIntent, REQUEST_PICK_APPLICATION);
} else {
- startActivityForResult(intent, REQUEST_CREATE_SHORTCUT);
+ startActivityForResultSafely(intent, REQUEST_CREATE_SHORTCUT);
}
}
@@ -1216,7 +1251,7 @@
if (folderName != null && folderName.equals(shortcutName)) {
addFolder();
} else {
- startActivityForResult(intent, REQUEST_CREATE_LIVE_FOLDER);
+ startActivityForResultSafely(intent, REQUEST_CREATE_LIVE_FOLDER);
}
}
@@ -1232,7 +1267,7 @@
LauncherModel.addItemToDatabase(this, folderInfo,
LauncherSettings.Favorites.CONTAINER_DESKTOP,
mWorkspace.getCurrentScreen(), cellInfo.cellX, cellInfo.cellY, false);
- mFolders.put(folderInfo.id, folderInfo);
+ sFolders.put(folderInfo.id, folderInfo);
// Create the view
FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon, this,
@@ -1242,7 +1277,7 @@
}
void removeFolder(FolderInfo folder) {
- mFolders.remove(folder.id);
+ sFolders.remove(folder.id);
}
private void completeAddLiveFolder(Intent data, CellLayout.CellInfo cellInfo) {
@@ -1297,7 +1332,7 @@
LauncherModel.addItemToDatabase(context, info, LauncherSettings.Favorites.CONTAINER_DESKTOP,
cellInfo.screen, cellInfo.cellX, cellInfo.cellY, notify);
- mFolders.put(info.id, info);
+ sFolders.put(info.id, info);
return info;
}
@@ -1847,7 +1882,7 @@
final String name = mInput.getText().toString();
if (!TextUtils.isEmpty(name)) {
// Make sure we have the right folder info
- mFolderInfo = mFolders.get(mFolderInfo.id);
+ mFolderInfo = sFolders.get(mFolderInfo.id);
mFolderInfo.title = name;
LauncherModel.updateItemInDatabase(Launcher.this, mFolderInfo);
@@ -2172,8 +2207,8 @@
* Implementation of the method from LauncherModel.Callbacks.
*/
public void bindFolders(HashMap<Long, FolderInfo> folders) {
- mFolders.clear();
- mFolders.putAll(folders);
+ sFolders.clear();
+ sFolders.putAll(folders);
}
/**
@@ -2226,7 +2261,7 @@
final long[] userFolders = mSavedState.getLongArray(RUNTIME_STATE_USER_FOLDERS);
if (userFolders != null) {
for (long folderId : userFolders) {
- final FolderInfo info = mFolders.get(folderId);
+ final FolderInfo info = sFolders.get(folderId);
if (info != null) {
openFolder(info);
}
@@ -2283,9 +2318,11 @@
*
* Implementation of the method from LauncherModel.Callbacks.
*/
- public void bindAppsRemoved(ArrayList<ApplicationInfo> apps) {
+ public void bindAppsRemoved(ArrayList<ApplicationInfo> apps, boolean permanent) {
removeDialog(DIALOG_CREATE_SHORTCUT);
- mWorkspace.removeItems(apps);
+ if (permanent) {
+ mWorkspace.removeItems(apps);
+ }
mAllAppsGrid.removeApps(apps);
}
@@ -2300,7 +2337,7 @@
Log.d(TAG, "mWaitingForResult=" + mWaitingForResult);
Log.d(TAG, "mSavedInstanceState=" + mSavedInstanceState);
Log.d(TAG, "mDesktopItems.size=" + mDesktopItems.size());
- Log.d(TAG, "mFolders.size=" + mFolders.size());
+ Log.d(TAG, "sFolders.size=" + sFolders.size());
mModel.dumpState();
mAllAppsGrid.dumpState();
Log.d(TAG, "END launcher2 dump state");
diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java
index 023264d..cb19fe3 100644
--- a/src/com/android/launcher2/LauncherModel.java
+++ b/src/com/android/launcher2/LauncherModel.java
@@ -35,7 +35,8 @@
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
-import android.os.Environment;
+import android.os.Handler;
+import android.os.HandlerThread;
import android.os.Parcelable;
import android.os.RemoteException;
import android.util.Log;
@@ -47,8 +48,8 @@
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Comparator;
import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
@@ -61,16 +62,22 @@
*/
public class LauncherModel extends BroadcastReceiver {
static final boolean DEBUG_LOADERS = false;
- static final boolean PROFILE_LOADERS = false;
static final String TAG = "Launcher.Model";
+ private static final int ITEMS_CHUNK = 6; // batch size for the workspace icons
private int mBatchSize; // 0 is all apps at once
private int mAllAppsLoadDelay; // milliseconds between batches
private final LauncherApplication mApp;
private final Object mLock = new Object();
private DeferredHandler mHandler = new DeferredHandler();
- private Loader mLoader = new Loader();
+ private LoaderTask mLoaderTask;
+
+ private static final HandlerThread sWorkerThread = new HandlerThread("launcher-loader");
+ static {
+ sWorkerThread.start();
+ }
+ private static final Handler sWorker = new Handler(sWorkerThread.getLooper());
// We start off with everything not loaded. After that, we assume that
// our monitoring of the package manager provides all updates and we never
@@ -78,12 +85,13 @@
private boolean mWorkspaceLoaded;
private boolean mAllAppsLoaded;
- private boolean mBeforeFirstLoad = true; // only access this from main thread
private WeakReference<Callbacks> mCallbacks;
- private final Object mAllAppsListLock = new Object();
- private AllAppsList mAllAppsList;
+ private AllAppsList mAllAppsList; // only access in worker thread
private IconCache mIconCache;
+ final ArrayList<ItemInfo> mItems = new ArrayList<ItemInfo>();
+ final ArrayList<LauncherAppWidgetInfo> mAppWidgets = new ArrayList<LauncherAppWidgetInfo>();
+ final HashMap<Long, FolderInfo> mFolders = new HashMap<Long, FolderInfo>();
private Bitmap mDefaultIcon;
@@ -97,7 +105,7 @@
public void bindAllApplications(ArrayList<ApplicationInfo> apps);
public void bindAppsAdded(ArrayList<ApplicationInfo> apps);
public void bindAppsUpdated(ArrayList<ApplicationInfo> apps);
- public void bindAppsRemoved(ArrayList<ApplicationInfo> apps);
+ public void bindAppsRemoved(ArrayList<ApplicationInfo> apps, boolean permanent);
public boolean isAllAppsVisible();
}
@@ -143,6 +151,7 @@
item.cellX = cellX;
item.cellY = cellY;
+ final Uri uri = LauncherSettings.Favorites.getContentUri(item.id, false);
final ContentValues values = new ContentValues();
final ContentResolver cr = context.getContentResolver();
@@ -151,7 +160,11 @@
values.put(LauncherSettings.Favorites.CELLY, item.cellY);
values.put(LauncherSettings.Favorites.SCREEN, item.screen);
- cr.update(LauncherSettings.Favorites.getContentUri(item.id, false), values, null, null);
+ sWorker.post(new Runnable() {
+ public void run() {
+ cr.update(uri, values, null, null);
+ }
+ });
}
/**
@@ -261,8 +274,12 @@
*/
static void deleteItemFromDatabase(Context context, ItemInfo item) {
final ContentResolver cr = context.getContentResolver();
-
- cr.delete(LauncherSettings.Favorites.getContentUri(item.id, false), null, null);
+ final Uri uriToDelete = LauncherSettings.Favorites.getContentUri(item.id, false);
+ sWorker.post(new Runnable() {
+ public void run() {
+ cr.delete(uriToDelete, null, null);
+ }
+ });
}
/**
@@ -285,295 +302,179 @@
}
}
- public void startLoader(Context context, boolean isLaunching) {
- mLoader.startLoader(context, isLaunching);
- }
-
- public void stopLoader() {
- mLoader.stopLoader();
- }
-
/**
* Call from the handler for ACTION_PACKAGE_ADDED, ACTION_PACKAGE_REMOVED and
* ACTION_PACKAGE_CHANGED.
*/
public void onReceive(Context context, Intent intent) {
- // Use the app as the context.
- context = mApp;
+ if (DEBUG_LOADERS) Log.d(TAG, "onReceive intent=" + intent);
+
+ final String action = intent.getAction();
- ArrayList<ApplicationInfo> added = null;
- ArrayList<ApplicationInfo> removed = null;
- ArrayList<ApplicationInfo> modified = null;
+ if (Intent.ACTION_PACKAGE_CHANGED.equals(action)
+ || Intent.ACTION_PACKAGE_REMOVED.equals(action)
+ || Intent.ACTION_PACKAGE_ADDED.equals(action)) {
+ final String packageName = intent.getData().getSchemeSpecificPart();
+ final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
- if (mBeforeFirstLoad) {
- // If we haven't even loaded yet, don't bother, since we'll just pick
- // up the changes.
- return;
+ int op = PackageUpdatedTask.OP_NONE;
+
+ if (packageName == null || packageName.length() == 0) {
+ // they sent us a bad intent
+ return;
+ }
+
+ if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
+ op = PackageUpdatedTask.OP_UPDATE;
+ } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
+ if (!replacing) {
+ op = PackageUpdatedTask.OP_REMOVE;
+ }
+ // else, we are replacing the package, so a PACKAGE_ADDED will be sent
+ // later, we will update the package at this time
+ } else if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
+ if (!replacing) {
+ op = PackageUpdatedTask.OP_ADD;
+ } else {
+ op = PackageUpdatedTask.OP_UPDATE;
+ }
+ }
+
+ if (op != PackageUpdatedTask.OP_NONE) {
+ enqueuePackageUpdated(new PackageUpdatedTask(op, new String[] { packageName }));
+ }
+
+ } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
+ // First, schedule to add these apps back in.
+ String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_ADD, packages));
+ // Then, rebind everything.
+ startLoader(mApp, false);
+
+ } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
+ String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ enqueuePackageUpdated(new PackageUpdatedTask(
+ PackageUpdatedTask.OP_UNAVAILABLE, packages));
+
}
+ }
- synchronized (mAllAppsListLock) {
- final String action = intent.getAction();
+ public void startLoader(Context context, boolean isLaunching) {
+ synchronized (mLock) {
+ if (DEBUG_LOADERS) {
+ Log.d(TAG, "startLoader isLaunching=" + isLaunching);
+ }
- if (Intent.ACTION_PACKAGE_CHANGED.equals(action)
- || Intent.ACTION_PACKAGE_REMOVED.equals(action)
- || Intent.ACTION_PACKAGE_ADDED.equals(action)) {
- final String packageName = intent.getData().getSchemeSpecificPart();
- final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
-
- if (packageName == null || packageName.length() == 0) {
- // they sent us a bad intent
- return;
- }
-
- if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
- mAllAppsList.updatePackage(context, packageName);
- } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
- if (!replacing) {
- mAllAppsList.removePackage(packageName);
+ // Don't bother to start the thread if we know it's not going to do anything
+ if (mCallbacks != null && mCallbacks.get() != null) {
+ // If there is already one running, tell it to stop.
+ LoaderTask oldTask = mLoaderTask;
+ if (oldTask != null) {
+ if (oldTask.isLaunching()) {
+ // don't downgrade isLaunching if we're already running
+ isLaunching = true;
}
- // else, we are replacing the package, so a PACKAGE_ADDED will be sent
- // later, we will update the package at this time
- } else if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
- if (!replacing) {
- mAllAppsList.addPackage(context, packageName);
- } else {
- mAllAppsList.updatePackage(context, packageName);
- }
+ oldTask.stopLocked();
}
-
- if (mAllAppsList.added.size() > 0) {
- added = mAllAppsList.added;
- mAllAppsList.added = new ArrayList<ApplicationInfo>();
- }
- if (mAllAppsList.removed.size() > 0) {
- removed = mAllAppsList.removed;
- mAllAppsList.removed = new ArrayList<ApplicationInfo>();
- for (ApplicationInfo info: removed) {
- mIconCache.remove(info.intent.getComponent());
- }
- }
- if (mAllAppsList.modified.size() > 0) {
- modified = mAllAppsList.modified;
- mAllAppsList.modified = new ArrayList<ApplicationInfo>();
- }
-
- final Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;
- if (callbacks == null) {
- Log.w(TAG, "Nobody to tell about the new app. Launcher is probably loading.");
- return;
- }
-
- if (added != null) {
- final ArrayList<ApplicationInfo> addedFinal = added;
- mHandler.post(new Runnable() {
- public void run() {
- callbacks.bindAppsAdded(addedFinal);
- }
- });
- }
- if (modified != null) {
- final ArrayList<ApplicationInfo> modifiedFinal = modified;
- mHandler.post(new Runnable() {
- public void run() {
- callbacks.bindAppsUpdated(modifiedFinal);
- }
- });
- }
- if (removed != null) {
- final ArrayList<ApplicationInfo> removedFinal = removed;
- mHandler.post(new Runnable() {
- public void run() {
- callbacks.bindAppsRemoved(removedFinal);
- }
- });
- }
- } else {
- if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
- String packages[] = intent.getStringArrayExtra(
- Intent.EXTRA_CHANGED_PACKAGE_LIST);
- if (packages == null || packages.length == 0) {
- return;
- }
- synchronized (this) {
- mAllAppsLoaded = mWorkspaceLoaded = false;
- }
- startLoader(context, false);
- } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
- String packages[] = intent.getStringArrayExtra(
- Intent.EXTRA_CHANGED_PACKAGE_LIST);
- if (packages == null || packages.length == 0) {
- return;
- }
- synchronized (this) {
- mAllAppsLoaded = mWorkspaceLoaded = false;
- }
- startLoader(context, false);
- }
+ mLoaderTask = new LoaderTask(context, isLaunching);
+ sWorker.post(mLoaderTask);
}
}
}
- public class Loader {
- private static final int ITEMS_CHUNK = 6;
-
- private LoaderThread mLoaderThread;
-
- final ArrayList<ItemInfo> mItems = new ArrayList<ItemInfo>();
- final ArrayList<LauncherAppWidgetInfo> mAppWidgets = new ArrayList<LauncherAppWidgetInfo>();
- final HashMap<Long, FolderInfo> mFolders = new HashMap<Long, FolderInfo>();
-
- /**
- * Call this from the ui thread so the handler is initialized on the correct thread.
- */
- public Loader() {
- }
-
- public void startLoader(Context context, boolean isLaunching) {
- synchronized (mLock) {
- if (DEBUG_LOADERS) {
- Log.d(TAG, "startLoader isLaunching=" + isLaunching);
- }
-
- // Don't bother to start the thread if we know it's not going to do anything
- if (mCallbacks != null && mCallbacks.get() != null) {
- LoaderThread oldThread = mLoaderThread;
- if (oldThread != null) {
- if (oldThread.isLaunching()) {
- // don't downgrade isLaunching if we're already running
- isLaunching = true;
- }
- oldThread.stopLocked();
- }
- mLoaderThread = new LoaderThread(context, oldThread, isLaunching);
- mLoaderThread.start();
- }
+ public void stopLoader() {
+ synchronized (mLock) {
+ if (mLoaderTask != null) {
+ mLoaderTask.stopLocked();
}
}
+ }
- public void stopLoader() {
- synchronized (mLock) {
- if (mLoaderThread != null) {
- mLoaderThread.stopLocked();
- }
- }
+ /**
+ * Runnable for the thread that loads the contents of the launcher:
+ * - workspace icons
+ * - widgets
+ * - all apps icons
+ */
+ private class LoaderTask implements Runnable {
+ private Context mContext;
+ private Thread mWaitThread;
+ private boolean mIsLaunching;
+ private boolean mStopped;
+ private boolean mLoadAndBindStepFinished;
+
+ LoaderTask(Context context, boolean isLaunching) {
+ mContext = context;
+ mIsLaunching = isLaunching;
}
- /**
- * Runnable for the thread that loads the contents of the launcher:
- * - workspace icons
- * - widgets
- * - all apps icons
- */
- private class LoaderThread extends Thread {
- private Context mContext;
- private Thread mWaitThread;
- private boolean mIsLaunching;
- private boolean mStopped;
- private boolean mLoadAndBindStepFinished;
+ boolean isLaunching() {
+ return mIsLaunching;
+ }
- LoaderThread(Context context, Thread waitThread, boolean isLaunching) {
- mContext = context;
- mWaitThread = waitThread;
- mIsLaunching = isLaunching;
+ private void loadAndBindWorkspace() {
+ // Load the workspace
+
+ // For now, just always reload the workspace. It's ~100 ms vs. the
+ // binding which takes many hundreds of ms.
+ // We can reconsider.
+ if (DEBUG_LOADERS) {
+ Log.d(TAG, "loadAndBindWorkspace mWorkspaceLoaded=" + mWorkspaceLoaded);
}
-
- boolean isLaunching() {
- return mIsLaunching;
- }
-
- /**
- * If another LoaderThread was supplied, we need to wait for that to finish before
- * we start our processing. This keeps the ordering of the setting and clearing
- * of the dirty flags correct by making sure we don't start processing stuff until
- * they've had a chance to re-set them. We do this waiting the worker thread, not
- * the ui thread to avoid ANRs.
- */
- private void waitForOtherThread() {
- if (mWaitThread != null) {
- boolean done = false;
- while (!done) {
- try {
- mWaitThread.join();
- done = true;
- } catch (InterruptedException ex) {
- // Ignore
- }
- }
- mWaitThread = null;
+ if (true || !mWorkspaceLoaded) {
+ loadWorkspace();
+ if (mStopped) {
+ return;
}
+ mWorkspaceLoaded = true;
}
- private void loadAndBindWorkspace() {
- // Load the workspace
+ // Bind the workspace
+ bindWorkspace();
+ }
- // Other other threads can unset mWorkspaceLoaded, so atomically set it,
- // and then if they unset it, or we unset it because of mStopped, it will
- // be unset.
- boolean loaded;
- synchronized (this) {
- loaded = mWorkspaceLoaded;
- mWorkspaceLoaded = true;
- }
+ private void waitForIdle() {
+ // Wait until the either we're stopped or the other threads are done.
+ // This way we don't start loading all apps until the workspace has settled
+ // down.
+ synchronized (LoaderTask.this) {
+ final long workspaceWaitTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
- // For now, just always reload the workspace. It's ~100 ms vs. the
- // binding which takes many hundreds of ms.
- // We can reconsider.
- if (DEBUG_LOADERS) Log.d(TAG, "loadAndBindWorkspace loaded=" + loaded);
- if (true || !loaded) {
- loadWorkspace();
- if (mStopped) {
- mWorkspaceLoaded = false;
- return;
- }
- }
-
- // Bind the workspace
- bindWorkspace();
- }
-
- private void waitForIdle() {
- // Wait until the either we're stopped or the other threads are done.
- // This way we don't start loading all apps until the workspace has settled
- // down.
- synchronized (LoaderThread.this) {
- final long workspaceWaitTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
-
- mHandler.postIdle(new Runnable() {
- public void run() {
- synchronized (LoaderThread.this) {
- mLoadAndBindStepFinished = true;
- if (DEBUG_LOADERS) {
- Log.d(TAG, "done with previous binding step");
- }
- LoaderThread.this.notify();
+ mHandler.postIdle(new Runnable() {
+ public void run() {
+ synchronized (LoaderTask.this) {
+ mLoadAndBindStepFinished = true;
+ if (DEBUG_LOADERS) {
+ Log.d(TAG, "done with previous binding step");
}
+ LoaderTask.this.notify();
}
- });
-
- while (!mStopped && !mLoadAndBindStepFinished) {
- try {
- this.wait();
- } catch (InterruptedException ex) {
- // Ignore
}
- }
- if (DEBUG_LOADERS) {
- Log.d(TAG, "waited "
- + (SystemClock.uptimeMillis()-workspaceWaitTime)
- + "ms for previous step to finish binding");
+ });
+
+ while (!mStopped && !mLoadAndBindStepFinished) {
+ try {
+ this.wait();
+ } catch (InterruptedException ex) {
+ // Ignore
}
}
+ if (DEBUG_LOADERS) {
+ Log.d(TAG, "waited "
+ + (SystemClock.uptimeMillis()-workspaceWaitTime)
+ + "ms for previous step to finish binding");
+ }
}
+ }
- public void run() {
- waitForOtherThread();
+ public void run() {
+ // Optimize for end-user experience: if the Launcher is up and // running with the
+ // All Apps interface in the foreground, load All Apps first. Otherwise, load the
+ // workspace first (default).
+ final Callbacks cbk = mCallbacks.get();
+ final boolean loadWorkspaceFirst = cbk != null ? (!cbk.isAllAppsVisible()) : true;
- // Optimize for end-user experience: if the Launcher is up and // running with the
- // All Apps interface in the foreground, load All Apps first. Otherwise, load the
- // workspace first (default).
- final Callbacks cbk = mCallbacks.get();
- final boolean loadWorkspaceFirst = cbk != null ? (!cbk.isAllAppsVisible()) : true;
-
+ keep_running: {
// Elevate priority when Home launches for the first time to avoid
// starving at boot time. Staring at a blank home is not cool.
synchronized (mLock) {
@@ -581,11 +482,6 @@
? Process.THREAD_PRIORITY_DEFAULT : Process.THREAD_PRIORITY_BACKGROUND);
}
- if (PROFILE_LOADERS) {
- android.os.Debug.startMethodTracing(
- Environment.getExternalStorageDirectory() + "/launcher-loaders");
- }
-
if (loadWorkspaceFirst) {
if (DEBUG_LOADERS) Log.d(TAG, "step 1: loading workspace");
loadAndBindWorkspace();
@@ -594,12 +490,18 @@
loadAndBindAllApps();
}
- // Whew! Hard work done.
+ if (mStopped) {
+ break keep_running;
+ }
+
+ // Whew! Hard work done. Slow us down, and wait until the UI thread has
+ // settled down.
synchronized (mLock) {
if (mIsLaunching) {
android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
}
}
+ waitForIdle();
// second step
if (loadWorkspaceFirst) {
@@ -609,671 +511,760 @@
if (DEBUG_LOADERS) Log.d(TAG, "step 2: special: loading workspace");
loadAndBindWorkspace();
}
+ }
- // Clear out this reference, otherwise we end up holding it until all of the
- // callback runnables are done.
- mContext = null;
+ // Clear out this reference, otherwise we end up holding it until all of the
+ // callback runnables are done.
+ mContext = null;
- synchronized (mLock) {
- // Setting the reference is atomic, but we can't do it inside the other critical
- // sections.
- mLoaderThread = null;
+ synchronized (mLock) {
+ // If we are still the last one to be scheduled, remove ourselves.
+ if (mLoaderTask == this) {
+ mLoaderTask = null;
}
+ }
- if (PROFILE_LOADERS) {
- android.os.Debug.stopMethodTracing();
- }
-
- // Trigger a gc to try to clean up after the stuff is done, since the
- // renderscript allocations aren't charged to the java heap.
+ // Trigger a gc to try to clean up after the stuff is done, since the
+ // renderscript allocations aren't charged to the java heap.
+ if (mStopped) {
mHandler.post(new Runnable() {
public void run() {
System.gc();
}
});
- }
-
- public void stopLocked() {
- synchronized (LoaderThread.this) {
- mStopped = true;
- this.notify();
- }
- }
-
- /**
- * Gets the callbacks object. If we've been stopped, or if the launcher object
- * has somehow been garbage collected, return null instead. Pass in the Callbacks
- * object that was around when the deferred message was scheduled, and if there's
- * a new Callbacks object around then also return null. This will save us from
- * calling onto it with data that will be ignored.
- */
- Callbacks tryGetCallbacks(Callbacks oldCallbacks) {
- synchronized (mLock) {
- if (mStopped) {
- return null;
- }
-
- if (mCallbacks == null) {
- return null;
- }
-
- final Callbacks callbacks = mCallbacks.get();
- if (callbacks != oldCallbacks) {
- return null;
- }
- if (callbacks == null) {
- Log.w(TAG, "no mCallbacks");
- return null;
- }
-
- return callbacks;
- }
- }
-
- // check & update map of what's occupied; used to discard overlapping/invalid items
- private boolean checkItemPlacement(ItemInfo occupied[][][], ItemInfo item) {
- if (item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
- return true;
- }
-
- for (int x = item.cellX; x < (item.cellX+item.spanX); x++) {
- for (int y = item.cellY; y < (item.cellY+item.spanY); y++) {
- if (occupied[item.screen][x][y] != null) {
- Log.e(TAG, "Error loading shortcut " + item
- + " into cell (" + item.screen + ":"
- + x + "," + y
- + ") occupied by "
- + occupied[item.screen][x][y]);
- return false;
+ } else {
+ mHandler.postIdle(new Runnable() {
+ public void run() {
+ System.gc();
}
- }
+ });
+ }
+ }
+
+ public void stopLocked() {
+ synchronized (LoaderTask.this) {
+ mStopped = true;
+ this.notify();
+ }
+ }
+
+ /**
+ * Gets the callbacks object. If we've been stopped, or if the launcher object
+ * has somehow been garbage collected, return null instead. Pass in the Callbacks
+ * object that was around when the deferred message was scheduled, and if there's
+ * a new Callbacks object around then also return null. This will save us from
+ * calling onto it with data that will be ignored.
+ */
+ Callbacks tryGetCallbacks(Callbacks oldCallbacks) {
+ synchronized (mLock) {
+ if (mStopped) {
+ return null;
}
- for (int x = item.cellX; x < (item.cellX+item.spanX); x++) {
- for (int y = item.cellY; y < (item.cellY+item.spanY); y++) {
- occupied[item.screen][x][y] = item;
- }
+
+ if (mCallbacks == null) {
+ return null;
}
+
+ final Callbacks callbacks = mCallbacks.get();
+ if (callbacks != oldCallbacks) {
+ return null;
+ }
+ if (callbacks == null) {
+ Log.w(TAG, "no mCallbacks");
+ return null;
+ }
+
+ return callbacks;
+ }
+ }
+
+ // check & update map of what's occupied; used to discard overlapping/invalid items
+ private boolean checkItemPlacement(ItemInfo occupied[][][], ItemInfo item) {
+ if (item.container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
return true;
}
- private void loadWorkspace() {
- final long t = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
+ for (int x = item.cellX; x < (item.cellX+item.spanX); x++) {
+ for (int y = item.cellY; y < (item.cellY+item.spanY); y++) {
+ if (occupied[item.screen][x][y] != null) {
+ Log.e(TAG, "Error loading shortcut " + item
+ + " into cell (" + item.screen + ":"
+ + x + "," + y
+ + ") occupied by "
+ + occupied[item.screen][x][y]);
+ return false;
+ }
+ }
+ }
+ for (int x = item.cellX; x < (item.cellX+item.spanX); x++) {
+ for (int y = item.cellY; y < (item.cellY+item.spanY); y++) {
+ occupied[item.screen][x][y] = item;
+ }
+ }
+ return true;
+ }
- final Context context = mContext;
- final ContentResolver contentResolver = context.getContentResolver();
- final PackageManager manager = context.getPackageManager();
- final AppWidgetManager widgets = AppWidgetManager.getInstance(context);
- final boolean isSafeMode = manager.isSafeMode();
+ private void loadWorkspace() {
+ final long t = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
- mItems.clear();
- mAppWidgets.clear();
- mFolders.clear();
+ final Context context = mContext;
+ final ContentResolver contentResolver = context.getContentResolver();
+ final PackageManager manager = context.getPackageManager();
+ final AppWidgetManager widgets = AppWidgetManager.getInstance(context);
+ final boolean isSafeMode = manager.isSafeMode();
- final ArrayList<Long> itemsToRemove = new ArrayList<Long>();
+ mItems.clear();
+ mAppWidgets.clear();
+ mFolders.clear();
- final Cursor c = contentResolver.query(
- LauncherSettings.Favorites.CONTENT_URI, null, null, null, null);
+ final ArrayList<Long> itemsToRemove = new ArrayList<Long>();
- final ItemInfo occupied[][][] = new ItemInfo[Launcher.SCREEN_COUNT][Launcher.NUMBER_CELLS_X][Launcher.NUMBER_CELLS_Y];
+ final Cursor c = contentResolver.query(
+ LauncherSettings.Favorites.CONTENT_URI, null, null, null, null);
- try {
- final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
- final int intentIndex = c.getColumnIndexOrThrow
- (LauncherSettings.Favorites.INTENT);
- final int titleIndex = c.getColumnIndexOrThrow
- (LauncherSettings.Favorites.TITLE);
- final int iconTypeIndex = c.getColumnIndexOrThrow(
- LauncherSettings.Favorites.ICON_TYPE);
- final int iconIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON);
- final int iconPackageIndex = c.getColumnIndexOrThrow(
- LauncherSettings.Favorites.ICON_PACKAGE);
- final int iconResourceIndex = c.getColumnIndexOrThrow(
- LauncherSettings.Favorites.ICON_RESOURCE);
- final int containerIndex = c.getColumnIndexOrThrow(
- LauncherSettings.Favorites.CONTAINER);
- final int itemTypeIndex = c.getColumnIndexOrThrow(
- LauncherSettings.Favorites.ITEM_TYPE);
- final int appWidgetIdIndex = c.getColumnIndexOrThrow(
- LauncherSettings.Favorites.APPWIDGET_ID);
- final int screenIndex = c.getColumnIndexOrThrow(
- LauncherSettings.Favorites.SCREEN);
- final int cellXIndex = c.getColumnIndexOrThrow
- (LauncherSettings.Favorites.CELLX);
- final int cellYIndex = c.getColumnIndexOrThrow
- (LauncherSettings.Favorites.CELLY);
- final int spanXIndex = c.getColumnIndexOrThrow
- (LauncherSettings.Favorites.SPANX);
- final int spanYIndex = c.getColumnIndexOrThrow(
- LauncherSettings.Favorites.SPANY);
- final int uriIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.URI);
- final int displayModeIndex = c.getColumnIndexOrThrow(
- LauncherSettings.Favorites.DISPLAY_MODE);
+ final ItemInfo occupied[][][] = new ItemInfo[Launcher.SCREEN_COUNT][Launcher.NUMBER_CELLS_X][Launcher.NUMBER_CELLS_Y];
- ShortcutInfo info;
- String intentDescription;
- LauncherAppWidgetInfo appWidgetInfo;
- int container;
- long id;
- Intent intent;
+ try {
+ final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
+ final int intentIndex = c.getColumnIndexOrThrow
+ (LauncherSettings.Favorites.INTENT);
+ final int titleIndex = c.getColumnIndexOrThrow
+ (LauncherSettings.Favorites.TITLE);
+ final int iconTypeIndex = c.getColumnIndexOrThrow(
+ LauncherSettings.Favorites.ICON_TYPE);
+ final int iconIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON);
+ final int iconPackageIndex = c.getColumnIndexOrThrow(
+ LauncherSettings.Favorites.ICON_PACKAGE);
+ final int iconResourceIndex = c.getColumnIndexOrThrow(
+ LauncherSettings.Favorites.ICON_RESOURCE);
+ final int containerIndex = c.getColumnIndexOrThrow(
+ LauncherSettings.Favorites.CONTAINER);
+ final int itemTypeIndex = c.getColumnIndexOrThrow(
+ LauncherSettings.Favorites.ITEM_TYPE);
+ final int appWidgetIdIndex = c.getColumnIndexOrThrow(
+ LauncherSettings.Favorites.APPWIDGET_ID);
+ final int screenIndex = c.getColumnIndexOrThrow(
+ LauncherSettings.Favorites.SCREEN);
+ final int cellXIndex = c.getColumnIndexOrThrow
+ (LauncherSettings.Favorites.CELLX);
+ final int cellYIndex = c.getColumnIndexOrThrow
+ (LauncherSettings.Favorites.CELLY);
+ final int spanXIndex = c.getColumnIndexOrThrow
+ (LauncherSettings.Favorites.SPANX);
+ final int spanYIndex = c.getColumnIndexOrThrow(
+ LauncherSettings.Favorites.SPANY);
+ final int uriIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.URI);
+ final int displayModeIndex = c.getColumnIndexOrThrow(
+ LauncherSettings.Favorites.DISPLAY_MODE);
- while (!mStopped && c.moveToNext()) {
- try {
- int itemType = c.getInt(itemTypeIndex);
+ ShortcutInfo info;
+ String intentDescription;
+ LauncherAppWidgetInfo appWidgetInfo;
+ int container;
+ long id;
+ Intent intent;
- switch (itemType) {
- case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
- case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
- intentDescription = c.getString(intentIndex);
- try {
- intent = Intent.parseUri(intentDescription, 0);
- } catch (URISyntaxException e) {
- continue;
- }
+ while (!mStopped && c.moveToNext()) {
+ try {
+ int itemType = c.getInt(itemTypeIndex);
- if (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
- info = getShortcutInfo(manager, intent, context, c, iconIndex,
- titleIndex);
- } else {
- info = getShortcutInfo(c, context, iconTypeIndex,
- iconPackageIndex, iconResourceIndex, iconIndex,
- titleIndex);
- }
+ switch (itemType) {
+ case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
+ case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
+ intentDescription = c.getString(intentIndex);
+ try {
+ intent = Intent.parseUri(intentDescription, 0);
+ } catch (URISyntaxException e) {
+ continue;
+ }
- if (info != null) {
- updateSavedIcon(context, info, c, iconIndex);
+ if (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
+ info = getShortcutInfo(manager, intent, context, c, iconIndex,
+ titleIndex);
+ } else {
+ info = getShortcutInfo(c, context, iconTypeIndex,
+ iconPackageIndex, iconResourceIndex, iconIndex,
+ titleIndex);
+ }
- info.intent = intent;
- info.id = c.getLong(idIndex);
- container = c.getInt(containerIndex);
- info.container = container;
- info.screen = c.getInt(screenIndex);
- info.cellX = c.getInt(cellXIndex);
- info.cellY = c.getInt(cellYIndex);
+ if (info != null) {
+ updateSavedIcon(context, info, c, iconIndex);
- // check & update map of what's occupied
- if (!checkItemPlacement(occupied, info)) {
- break;
- }
-
- switch (container) {
- case LauncherSettings.Favorites.CONTAINER_DESKTOP:
- mItems.add(info);
- break;
- default:
- // Item is in a user folder
- UserFolderInfo folderInfo =
- findOrMakeUserFolder(mFolders, container);
- folderInfo.add(info);
- break;
- }
- } else {
- // Failed to load the shortcut, probably because the
- // activity manager couldn't resolve it (maybe the app
- // was uninstalled), or the db row was somehow screwed up.
- // Delete it.
- id = c.getLong(idIndex);
- Log.e(TAG, "Error loading shortcut " + id + ", removing it");
- contentResolver.delete(LauncherSettings.Favorites.getContentUri(
- id, false), null, null);
- }
- break;
-
- case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
- id = c.getLong(idIndex);
- UserFolderInfo folderInfo = findOrMakeUserFolder(mFolders, id);
-
- folderInfo.title = c.getString(titleIndex);
-
- folderInfo.id = id;
+ info.intent = intent;
+ info.id = c.getLong(idIndex);
container = c.getInt(containerIndex);
- folderInfo.container = container;
- folderInfo.screen = c.getInt(screenIndex);
- folderInfo.cellX = c.getInt(cellXIndex);
- folderInfo.cellY = c.getInt(cellYIndex);
+ info.container = container;
+ info.screen = c.getInt(screenIndex);
+ info.cellX = c.getInt(cellXIndex);
+ info.cellY = c.getInt(cellYIndex);
// check & update map of what's occupied
- if (!checkItemPlacement(occupied, folderInfo)) {
+ if (!checkItemPlacement(occupied, info)) {
break;
}
switch (container) {
+ case LauncherSettings.Favorites.CONTAINER_DESKTOP:
+ mItems.add(info);
+ break;
+ default:
+ // Item is in a user folder
+ UserFolderInfo folderInfo =
+ findOrMakeUserFolder(mFolders, container);
+ folderInfo.add(info);
+ break;
+ }
+ } else {
+ // Failed to load the shortcut, probably because the
+ // activity manager couldn't resolve it (maybe the app
+ // was uninstalled), or the db row was somehow screwed up.
+ // Delete it.
+ id = c.getLong(idIndex);
+ Log.e(TAG, "Error loading shortcut " + id + ", removing it");
+ contentResolver.delete(LauncherSettings.Favorites.getContentUri(
+ id, false), null, null);
+ }
+ break;
+
+ case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
+ id = c.getLong(idIndex);
+ UserFolderInfo folderInfo = findOrMakeUserFolder(mFolders, id);
+
+ folderInfo.title = c.getString(titleIndex);
+
+ folderInfo.id = id;
+ container = c.getInt(containerIndex);
+ folderInfo.container = container;
+ folderInfo.screen = c.getInt(screenIndex);
+ folderInfo.cellX = c.getInt(cellXIndex);
+ folderInfo.cellY = c.getInt(cellYIndex);
+
+ // check & update map of what's occupied
+ if (!checkItemPlacement(occupied, folderInfo)) {
+ break;
+ }
+
+ switch (container) {
+ case LauncherSettings.Favorites.CONTAINER_DESKTOP:
+ mItems.add(folderInfo);
+ break;
+ }
+
+ mFolders.put(folderInfo.id, folderInfo);
+ break;
+
+ case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
+ id = c.getLong(idIndex);
+ Uri uri = Uri.parse(c.getString(uriIndex));
+
+ // Make sure the live folder exists
+ final ProviderInfo providerInfo =
+ context.getPackageManager().resolveContentProvider(
+ uri.getAuthority(), 0);
+
+ if (providerInfo == null && !isSafeMode) {
+ itemsToRemove.add(id);
+ } else {
+ LiveFolderInfo liveFolderInfo = findOrMakeLiveFolder(mFolders, id);
+
+ intentDescription = c.getString(intentIndex);
+ intent = null;
+ if (intentDescription != null) {
+ try {
+ intent = Intent.parseUri(intentDescription, 0);
+ } catch (URISyntaxException e) {
+ // Ignore, a live folder might not have a base intent
+ }
+ }
+
+ liveFolderInfo.title = c.getString(titleIndex);
+ liveFolderInfo.id = id;
+ liveFolderInfo.uri = uri;
+ container = c.getInt(containerIndex);
+ liveFolderInfo.container = container;
+ liveFolderInfo.screen = c.getInt(screenIndex);
+ liveFolderInfo.cellX = c.getInt(cellXIndex);
+ liveFolderInfo.cellY = c.getInt(cellYIndex);
+ liveFolderInfo.baseIntent = intent;
+ liveFolderInfo.displayMode = c.getInt(displayModeIndex);
+
+ // check & update map of what's occupied
+ if (!checkItemPlacement(occupied, liveFolderInfo)) {
+ break;
+ }
+
+ loadLiveFolderIcon(context, c, iconTypeIndex, iconPackageIndex,
+ iconResourceIndex, liveFolderInfo);
+
+ switch (container) {
case LauncherSettings.Favorites.CONTAINER_DESKTOP:
- mItems.add(folderInfo);
+ mItems.add(liveFolderInfo);
break;
}
-
- mFolders.put(folderInfo.id, folderInfo);
- break;
-
- case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
- id = c.getLong(idIndex);
- Uri uri = Uri.parse(c.getString(uriIndex));
-
- // Make sure the live folder exists
- final ProviderInfo providerInfo =
- context.getPackageManager().resolveContentProvider(
- uri.getAuthority(), 0);
-
- if (providerInfo == null && !isSafeMode) {
- itemsToRemove.add(id);
- } else {
- LiveFolderInfo liveFolderInfo = findOrMakeLiveFolder(mFolders, id);
-
- intentDescription = c.getString(intentIndex);
- intent = null;
- if (intentDescription != null) {
- try {
- intent = Intent.parseUri(intentDescription, 0);
- } catch (URISyntaxException e) {
- // Ignore, a live folder might not have a base intent
- }
- }
-
- liveFolderInfo.title = c.getString(titleIndex);
- liveFolderInfo.id = id;
- liveFolderInfo.uri = uri;
- container = c.getInt(containerIndex);
- liveFolderInfo.container = container;
- liveFolderInfo.screen = c.getInt(screenIndex);
- liveFolderInfo.cellX = c.getInt(cellXIndex);
- liveFolderInfo.cellY = c.getInt(cellYIndex);
- liveFolderInfo.baseIntent = intent;
- liveFolderInfo.displayMode = c.getInt(displayModeIndex);
-
- // check & update map of what's occupied
- if (!checkItemPlacement(occupied, liveFolderInfo)) {
- break;
- }
-
- loadLiveFolderIcon(context, c, iconTypeIndex, iconPackageIndex,
- iconResourceIndex, liveFolderInfo);
-
- switch (container) {
- case LauncherSettings.Favorites.CONTAINER_DESKTOP:
- mItems.add(liveFolderInfo);
- break;
- }
- mFolders.put(liveFolderInfo.id, liveFolderInfo);
- }
- break;
-
- case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
- // Read all Launcher-specific widget details
- int appWidgetId = c.getInt(appWidgetIdIndex);
- id = c.getLong(idIndex);
-
- final AppWidgetProviderInfo provider =
- widgets.getAppWidgetInfo(appWidgetId);
-
- if (!isSafeMode && (provider == null || provider.provider == null ||
- provider.provider.getPackageName() == null)) {
- Log.e(TAG, "Deleting widget that isn't installed anymore: id="
- + id + " appWidgetId=" + appWidgetId);
- itemsToRemove.add(id);
- } else {
- appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId);
- appWidgetInfo.id = id;
- appWidgetInfo.screen = c.getInt(screenIndex);
- appWidgetInfo.cellX = c.getInt(cellXIndex);
- appWidgetInfo.cellY = c.getInt(cellYIndex);
- appWidgetInfo.spanX = c.getInt(spanXIndex);
- appWidgetInfo.spanY = c.getInt(spanYIndex);
-
- container = c.getInt(containerIndex);
- if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
- Log.e(TAG, "Widget found where container "
- + "!= CONTAINER_DESKTOP -- ignoring!");
- continue;
- }
- appWidgetInfo.container = c.getInt(containerIndex);
-
- // check & update map of what's occupied
- if (!checkItemPlacement(occupied, appWidgetInfo)) {
- break;
- }
-
- mAppWidgets.add(appWidgetInfo);
- }
- break;
+ mFolders.put(liveFolderInfo.id, liveFolderInfo);
}
- } catch (Exception e) {
- Log.w(TAG, "Desktop items loading interrupted:", e);
- }
- }
- } finally {
- c.close();
- }
+ break;
- if (itemsToRemove.size() > 0) {
- ContentProviderClient client = contentResolver.acquireContentProviderClient(
- LauncherSettings.Favorites.CONTENT_URI);
- // Remove dead items
- for (long id : itemsToRemove) {
- if (DEBUG_LOADERS) {
- Log.d(TAG, "Removed id = " + id);
+ case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
+ // Read all Launcher-specific widget details
+ int appWidgetId = c.getInt(appWidgetIdIndex);
+ id = c.getLong(idIndex);
+
+ final AppWidgetProviderInfo provider =
+ widgets.getAppWidgetInfo(appWidgetId);
+
+ if (!isSafeMode && (provider == null || provider.provider == null ||
+ provider.provider.getPackageName() == null)) {
+ Log.e(TAG, "Deleting widget that isn't installed anymore: id="
+ + id + " appWidgetId=" + appWidgetId);
+ itemsToRemove.add(id);
+ } else {
+ appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId);
+ appWidgetInfo.id = id;
+ appWidgetInfo.screen = c.getInt(screenIndex);
+ appWidgetInfo.cellX = c.getInt(cellXIndex);
+ appWidgetInfo.cellY = c.getInt(cellYIndex);
+ appWidgetInfo.spanX = c.getInt(spanXIndex);
+ appWidgetInfo.spanY = c.getInt(spanYIndex);
+
+ container = c.getInt(containerIndex);
+ if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+ Log.e(TAG, "Widget found where container "
+ + "!= CONTAINER_DESKTOP -- ignoring!");
+ continue;
+ }
+ appWidgetInfo.container = c.getInt(containerIndex);
+
+ // check & update map of what's occupied
+ if (!checkItemPlacement(occupied, appWidgetInfo)) {
+ break;
+ }
+
+ mAppWidgets.add(appWidgetInfo);
+ }
+ break;
}
- // Don't notify content observers
- try {
- client.delete(LauncherSettings.Favorites.getContentUri(id, false),
- null, null);
- } catch (RemoteException e) {
- Log.w(TAG, "Could not remove id = " + id);
- }
+ } catch (Exception e) {
+ Log.w(TAG, "Desktop items loading interrupted:", e);
}
}
+ } finally {
+ c.close();
+ }
- if (DEBUG_LOADERS) {
- Log.d(TAG, "loaded workspace in " + (SystemClock.uptimeMillis()-t) + "ms");
- Log.d(TAG, "workspace layout: ");
- for (int y = 0; y < Launcher.NUMBER_CELLS_Y; y++) {
- String line = "";
- for (int s = 0; s < Launcher.SCREEN_COUNT; s++) {
- if (s > 0) {
- line += " | ";
- }
- for (int x = 0; x < Launcher.NUMBER_CELLS_X; x++) {
- line += ((occupied[s][x][y] != null) ? "#" : ".");
- }
- }
- Log.d(TAG, "[ " + line + " ]");
+ if (itemsToRemove.size() > 0) {
+ ContentProviderClient client = contentResolver.acquireContentProviderClient(
+ LauncherSettings.Favorites.CONTENT_URI);
+ // Remove dead items
+ for (long id : itemsToRemove) {
+ if (DEBUG_LOADERS) {
+ Log.d(TAG, "Removed id = " + id);
+ }
+ // Don't notify content observers
+ try {
+ client.delete(LauncherSettings.Favorites.getContentUri(id, false),
+ null, null);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Could not remove id = " + id);
}
}
}
- /**
- * Read everything out of our database.
- */
- private void bindWorkspace() {
- final long t = SystemClock.uptimeMillis();
-
- // Don't use these two variables in any of the callback runnables.
- // Otherwise we hold a reference to them.
- final Callbacks oldCallbacks = mCallbacks.get();
- if (oldCallbacks == null) {
- // This launcher has exited and nobody bothered to tell us. Just bail.
- Log.w(TAG, "LoaderThread running with no launcher");
- return;
+ if (DEBUG_LOADERS) {
+ Log.d(TAG, "loaded workspace in " + (SystemClock.uptimeMillis()-t) + "ms");
+ Log.d(TAG, "workspace layout: ");
+ for (int y = 0; y < Launcher.NUMBER_CELLS_Y; y++) {
+ String line = "";
+ for (int s = 0; s < Launcher.SCREEN_COUNT; s++) {
+ if (s > 0) {
+ line += " | ";
+ }
+ for (int x = 0; x < Launcher.NUMBER_CELLS_X; x++) {
+ line += ((occupied[s][x][y] != null) ? "#" : ".");
+ }
+ }
+ Log.d(TAG, "[ " + line + " ]");
}
+ }
+ }
- int N;
- // Tell the workspace that we're about to start firing items at it
+ /**
+ * Read everything out of our database.
+ */
+ private void bindWorkspace() {
+ final long t = SystemClock.uptimeMillis();
+
+ // Don't use these two variables in any of the callback runnables.
+ // Otherwise we hold a reference to them.
+ final Callbacks oldCallbacks = mCallbacks.get();
+ if (oldCallbacks == null) {
+ // This launcher has exited and nobody bothered to tell us. Just bail.
+ Log.w(TAG, "LoaderTask running with no launcher");
+ return;
+ }
+
+ int N;
+ // Tell the workspace that we're about to start firing items at it
+ mHandler.post(new Runnable() {
+ public void run() {
+ Callbacks callbacks = tryGetCallbacks(oldCallbacks);
+ if (callbacks != null) {
+ callbacks.startBinding();
+ }
+ }
+ });
+ // Add the items to the workspace.
+ N = mItems.size();
+ for (int i=0; i<N; i+=ITEMS_CHUNK) {
+ final int start = i;
+ final int chunkSize = (i+ITEMS_CHUNK <= N) ? ITEMS_CHUNK : (N-i);
mHandler.post(new Runnable() {
public void run() {
Callbacks callbacks = tryGetCallbacks(oldCallbacks);
if (callbacks != null) {
- callbacks.startBinding();
+ callbacks.bindItems(mItems, start, start+chunkSize);
}
}
});
- // Add the items to the workspace.
- N = mItems.size();
- for (int i=0; i<N; i+=ITEMS_CHUNK) {
- final int start = i;
- final int chunkSize = (i+ITEMS_CHUNK <= N) ? ITEMS_CHUNK : (N-i);
+ }
+ mHandler.post(new Runnable() {
+ public void run() {
+ Callbacks callbacks = tryGetCallbacks(oldCallbacks);
+ if (callbacks != null) {
+ callbacks.bindFolders(mFolders);
+ }
+ }
+ });
+ // Wait until the queue goes empty.
+ mHandler.post(new Runnable() {
+ public void run() {
+ if (DEBUG_LOADERS) {
+ Log.d(TAG, "Going to start binding widgets soon.");
+ }
+ }
+ });
+ // Bind the widgets, one at a time.
+ // WARNING: this is calling into the workspace from the background thread,
+ // but since getCurrentScreen() just returns the int, we should be okay. This
+ // is just a hint for the order, and if it's wrong, we'll be okay.
+ // TODO: instead, we should have that push the current screen into here.
+ final int currentScreen = oldCallbacks.getCurrentWorkspaceScreen();
+ N = mAppWidgets.size();
+ // once for the current screen
+ for (int i=0; i<N; i++) {
+ final LauncherAppWidgetInfo widget = mAppWidgets.get(i);
+ if (widget.screen == currentScreen) {
mHandler.post(new Runnable() {
public void run() {
Callbacks callbacks = tryGetCallbacks(oldCallbacks);
if (callbacks != null) {
- callbacks.bindItems(mItems, start, start+chunkSize);
+ callbacks.bindAppWidget(widget);
}
}
});
}
- mHandler.post(new Runnable() {
- public void run() {
- Callbacks callbacks = tryGetCallbacks(oldCallbacks);
- if (callbacks != null) {
- callbacks.bindFolders(mFolders);
- }
- }
- });
- // Wait until the queue goes empty.
- mHandler.post(new Runnable() {
- public void run() {
- if (DEBUG_LOADERS) {
- Log.d(TAG, "Going to start binding widgets soon.");
- }
- }
- });
- // Bind the widgets, one at a time.
- // WARNING: this is calling into the workspace from the background thread,
- // but since getCurrentScreen() just returns the int, we should be okay. This
- // is just a hint for the order, and if it's wrong, we'll be okay.
- // TODO: instead, we should have that push the current screen into here.
- final int currentScreen = oldCallbacks.getCurrentWorkspaceScreen();
- N = mAppWidgets.size();
- // once for the current screen
- for (int i=0; i<N; i++) {
- final LauncherAppWidgetInfo widget = mAppWidgets.get(i);
- if (widget.screen == currentScreen) {
- mHandler.post(new Runnable() {
- public void run() {
- Callbacks callbacks = tryGetCallbacks(oldCallbacks);
- if (callbacks != null) {
- callbacks.bindAppWidget(widget);
- }
- }
- });
- }
- }
- // once for the other screens
- for (int i=0; i<N; i++) {
- final LauncherAppWidgetInfo widget = mAppWidgets.get(i);
- if (widget.screen != currentScreen) {
- mHandler.post(new Runnable() {
- public void run() {
- Callbacks callbacks = tryGetCallbacks(oldCallbacks);
- if (callbacks != null) {
- callbacks.bindAppWidget(widget);
- }
- }
- });
- }
- }
- // Tell the workspace that we're done.
- mHandler.post(new Runnable() {
- public void run() {
- Callbacks callbacks = tryGetCallbacks(oldCallbacks);
- if (callbacks != null) {
- callbacks.finishBindingItems();
- }
- }
- });
- // If we're profiling, this is the last thing in the queue.
- mHandler.post(new Runnable() {
- public void run() {
- if (DEBUG_LOADERS) {
- Log.d(TAG, "bound workspace in "
- + (SystemClock.uptimeMillis()-t) + "ms");
- }
- }
- });
}
-
- private void loadAndBindAllApps() {
- // Other other threads can unset mAllAppsLoaded, so atomically set it,
- // and then if they unset it, or we unset it because of mStopped, it will
- // be unset.
- boolean loaded;
- synchronized (this) {
- loaded = mAllAppsLoaded;
- mAllAppsLoaded = true;
- }
-
- if (DEBUG_LOADERS) Log.d(TAG, "loadAndBindAllApps loaded=" + loaded);
- if (!loaded) {
- loadAllAppsByBatch();
- if (mStopped) {
- mAllAppsLoaded = false;
- return;
- }
- } else {
- onlyBindAllApps();
+ // once for the other screens
+ for (int i=0; i<N; i++) {
+ final LauncherAppWidgetInfo widget = mAppWidgets.get(i);
+ if (widget.screen != currentScreen) {
+ mHandler.post(new Runnable() {
+ public void run() {
+ Callbacks callbacks = tryGetCallbacks(oldCallbacks);
+ if (callbacks != null) {
+ callbacks.bindAppWidget(widget);
+ }
+ }
+ });
}
}
+ // Tell the workspace that we're done.
+ mHandler.post(new Runnable() {
+ public void run() {
+ Callbacks callbacks = tryGetCallbacks(oldCallbacks);
+ if (callbacks != null) {
+ callbacks.finishBindingItems();
+ }
+ }
+ });
+ // If we're profiling, this is the last thing in the queue.
+ mHandler.post(new Runnable() {
+ public void run() {
+ if (DEBUG_LOADERS) {
+ Log.d(TAG, "bound workspace in "
+ + (SystemClock.uptimeMillis()-t) + "ms");
+ }
+ }
+ });
+ }
- private void onlyBindAllApps() {
- final Callbacks oldCallbacks = mCallbacks.get();
- if (oldCallbacks == null) {
- // This launcher has exited and nobody bothered to tell us. Just bail.
- Log.w(TAG, "LoaderThread running with no launcher (onlyBindAllApps)");
+ private void loadAndBindAllApps() {
+ if (DEBUG_LOADERS) {
+ Log.d(TAG, "loadAndBindAllApps mAllAppsLoaded=" + mAllAppsLoaded);
+ }
+ if (!mAllAppsLoaded) {
+ loadAllAppsByBatch();
+ if (mStopped) {
return;
}
+ mAllAppsLoaded = true;
+ } else {
+ onlyBindAllApps();
+ }
+ }
- // shallow copy
- final ArrayList<ApplicationInfo> list
- = (ArrayList<ApplicationInfo>)mAllAppsList.data.clone();
+ private void onlyBindAllApps() {
+ final Callbacks oldCallbacks = mCallbacks.get();
+ if (oldCallbacks == null) {
+ // This launcher has exited and nobody bothered to tell us. Just bail.
+ Log.w(TAG, "LoaderTask running with no launcher (onlyBindAllApps)");
+ return;
+ }
+
+ // shallow copy
+ final ArrayList<ApplicationInfo> list
+ = (ArrayList<ApplicationInfo>)mAllAppsList.data.clone();
+ mHandler.post(new Runnable() {
+ public void run() {
+ final long t = SystemClock.uptimeMillis();
+ final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
+ if (callbacks != null) {
+ callbacks.bindAllApplications(list);
+ }
+ if (DEBUG_LOADERS) {
+ Log.d(TAG, "bound all " + list.size() + " apps from cache in "
+ + (SystemClock.uptimeMillis()-t) + "ms");
+ }
+ }
+ });
+
+ }
+
+ private void loadAllAppsByBatch() {
+ final long t = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
+
+ // Don't use these two variables in any of the callback runnables.
+ // Otherwise we hold a reference to them.
+ final Callbacks oldCallbacks = mCallbacks.get();
+ if (oldCallbacks == null) {
+ // This launcher has exited and nobody bothered to tell us. Just bail.
+ Log.w(TAG, "LoaderTask running with no launcher (loadAllAppsByBatch)");
+ return;
+ }
+
+ final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
+ mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+
+ final PackageManager packageManager = mContext.getPackageManager();
+ List<ResolveInfo> apps = null;
+
+ int N = Integer.MAX_VALUE;
+
+ int startIndex;
+ int i=0;
+ int batchSize = -1;
+ while (i < N && !mStopped) {
+ if (i == 0) {
+ mAllAppsList.clear();
+ final long qiaTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
+ apps = packageManager.queryIntentActivities(mainIntent, 0);
+ if (DEBUG_LOADERS) {
+ Log.d(TAG, "queryIntentActivities took "
+ + (SystemClock.uptimeMillis()-qiaTime) + "ms");
+ }
+ if (apps == null) {
+ return;
+ }
+ N = apps.size();
+ if (DEBUG_LOADERS) {
+ Log.d(TAG, "queryIntentActivities got " + N + " apps");
+ }
+ if (N == 0) {
+ // There are no apps?!?
+ return;
+ }
+ if (mBatchSize == 0) {
+ batchSize = N;
+ } else {
+ batchSize = mBatchSize;
+ }
+
+ final long sortTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
+ Collections.sort(apps,
+ new ResolveInfo.DisplayNameComparator(packageManager));
+ if (DEBUG_LOADERS) {
+ Log.d(TAG, "sort took "
+ + (SystemClock.uptimeMillis()-sortTime) + "ms");
+ }
+ }
+
+ final long t2 = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
+
+ startIndex = i;
+ for (int j=0; i<N && j<batchSize; j++) {
+ // This builds the icon bitmaps.
+ mAllAppsList.add(new ApplicationInfo(apps.get(i), mIconCache));
+ i++;
+ }
+
+ final boolean first = i <= batchSize;
+ final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
+ final ArrayList<ApplicationInfo> added = mAllAppsList.added;
+ mAllAppsList.added = new ArrayList<ApplicationInfo>();
+
mHandler.post(new Runnable() {
public void run() {
final long t = SystemClock.uptimeMillis();
- final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
if (callbacks != null) {
- callbacks.bindAllApplications(list);
- }
- if (DEBUG_LOADERS) {
- Log.d(TAG, "bound all " + list.size() + " apps from cache in "
- + (SystemClock.uptimeMillis()-t) + "ms");
+ if (first) {
+ callbacks.bindAllApplications(added);
+ } else {
+ callbacks.bindAppsAdded(added);
+ }
+ if (DEBUG_LOADERS) {
+ Log.d(TAG, "bound " + added.size() + " apps in "
+ + (SystemClock.uptimeMillis() - t) + "ms");
+ }
+ } else {
+ Log.i(TAG, "not binding apps: no Launcher activity");
}
}
});
- }
-
- private void loadAllAppsByBatch() {
- final long t = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
-
- // Don't use these two variables in any of the callback runnables.
- // Otherwise we hold a reference to them.
- final Callbacks oldCallbacks = mCallbacks.get();
- if (oldCallbacks == null) {
- // This launcher has exited and nobody bothered to tell us. Just bail.
- Log.w(TAG, "LoaderThread running with no launcher (loadAllAppsByBatch)");
- return;
- }
-
- final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
- mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
-
- final PackageManager packageManager = mContext.getPackageManager();
- List<ResolveInfo> apps = null;
-
- int N = Integer.MAX_VALUE;
-
- int startIndex;
- int i=0;
- int batchSize = -1;
- while (i < N && !mStopped) {
- synchronized (mAllAppsListLock) {
- if (i == 0) {
- // This needs to happen inside the same lock block as when we
- // prepare the first batch for bindAllApplications. Otherwise
- // the package changed receiver can come in and double-add
- // (or miss one?).
- mAllAppsList.clear();
- final long qiaTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
- apps = packageManager.queryIntentActivities(mainIntent, 0);
- if (DEBUG_LOADERS) {
- Log.d(TAG, "queryIntentActivities took "
- + (SystemClock.uptimeMillis()-qiaTime) + "ms");
- }
- if (apps == null) {
- return;
- }
- N = apps.size();
- if (DEBUG_LOADERS) {
- Log.d(TAG, "queryIntentActivities got " + N + " apps");
- }
- if (N == 0) {
- // There are no apps?!?
- return;
- }
- if (mBatchSize == 0) {
- batchSize = N;
- } else {
- batchSize = mBatchSize;
- }
-
- final long sortTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
- Collections.sort(apps,
- new ResolveInfo.DisplayNameComparator(packageManager));
- if (DEBUG_LOADERS) {
- Log.d(TAG, "sort took "
- + (SystemClock.uptimeMillis()-sortTime) + "ms");
- }
- }
-
- final long t2 = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
-
- startIndex = i;
- for (int j=0; i<N && j<batchSize; j++) {
- // This builds the icon bitmaps.
- mAllAppsList.add(new ApplicationInfo(apps.get(i), mIconCache));
- i++;
- }
-
- final boolean first = i <= batchSize;
- final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
- final ArrayList<ApplicationInfo> added = mAllAppsList.added;
- mAllAppsList.added = new ArrayList<ApplicationInfo>();
-
- mHandler.post(new Runnable() {
- public void run() {
- final long t = SystemClock.uptimeMillis();
- if (callbacks != null) {
- if (first) {
- mBeforeFirstLoad = false;
- callbacks.bindAllApplications(added);
- } else {
- callbacks.bindAppsAdded(added);
- }
- if (DEBUG_LOADERS) {
- Log.d(TAG, "bound " + added.size() + " apps in "
- + (SystemClock.uptimeMillis() - t) + "ms");
- }
- } else {
- Log.i(TAG, "not binding apps: no Launcher activity");
- }
- }
- });
-
- if (DEBUG_LOADERS) {
- Log.d(TAG, "batch of " + (i-startIndex) + " icons processed in "
- + (SystemClock.uptimeMillis()-t2) + "ms");
- }
- }
-
- if (mAllAppsLoadDelay > 0 && i < N) {
- try {
- if (DEBUG_LOADERS) {
- Log.d(TAG, "sleeping for " + mAllAppsLoadDelay + "ms");
- }
- Thread.sleep(mAllAppsLoadDelay);
- } catch (InterruptedException exc) { }
- }
- }
-
if (DEBUG_LOADERS) {
- Log.d(TAG, "cached all " + N + " apps in "
- + (SystemClock.uptimeMillis()-t) + "ms"
- + (mAllAppsLoadDelay > 0 ? " (including delay)" : ""));
+ Log.d(TAG, "batch of " + (i-startIndex) + " icons processed in "
+ + (SystemClock.uptimeMillis()-t2) + "ms");
+ }
+
+ if (mAllAppsLoadDelay > 0 && i < N) {
+ try {
+ if (DEBUG_LOADERS) {
+ Log.d(TAG, "sleeping for " + mAllAppsLoadDelay + "ms");
+ }
+ Thread.sleep(mAllAppsLoadDelay);
+ } catch (InterruptedException exc) { }
}
}
- public void dumpState() {
- Log.d(TAG, "mLoader.mLoaderThread.mContext=" + mContext);
- Log.d(TAG, "mLoader.mLoaderThread.mWaitThread=" + mWaitThread);
- Log.d(TAG, "mLoader.mLoaderThread.mIsLaunching=" + mIsLaunching);
- Log.d(TAG, "mLoader.mLoaderThread.mStopped=" + mStopped);
- Log.d(TAG, "mLoader.mLoaderThread.mLoadAndBindStepFinished=" + mLoadAndBindStepFinished);
+ if (DEBUG_LOADERS) {
+ Log.d(TAG, "cached all " + N + " apps in "
+ + (SystemClock.uptimeMillis()-t) + "ms"
+ + (mAllAppsLoadDelay > 0 ? " (including delay)" : ""));
}
}
public void dumpState() {
- Log.d(TAG, "mLoader.mItems size=" + mLoader.mItems.size());
- if (mLoaderThread != null) {
- mLoaderThread.dumpState();
- } else {
- Log.d(TAG, "mLoader.mLoaderThread=null");
+ Log.d(TAG, "mLoaderTask.mContext=" + mContext);
+ Log.d(TAG, "mLoaderTask.mWaitThread=" + mWaitThread);
+ Log.d(TAG, "mLoaderTask.mIsLaunching=" + mIsLaunching);
+ Log.d(TAG, "mLoaderTask.mStopped=" + mStopped);
+ Log.d(TAG, "mLoaderTask.mLoadAndBindStepFinished=" + mLoadAndBindStepFinished);
+ }
+ }
+
+ void enqueuePackageUpdated(PackageUpdatedTask task) {
+ sWorker.post(task);
+ }
+
+ private class PackageUpdatedTask implements Runnable {
+ int mOp;
+ String[] mPackages;
+
+ public static final int OP_NONE = 0;
+ public static final int OP_ADD = 1;
+ public static final int OP_UPDATE = 2;
+ public static final int OP_REMOVE = 3; // uninstlled
+ public static final int OP_UNAVAILABLE = 4; // external media unmounted
+
+
+ public PackageUpdatedTask(int op, String[] packages) {
+ mOp = op;
+ mPackages = packages;
+ }
+
+ public void run() {
+ final Context context = mApp;
+
+ final String[] packages = mPackages;
+ final int N = packages.length;
+ switch (mOp) {
+ case OP_ADD:
+ for (int i=0; i<N; i++) {
+ if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.addPackage " + packages[i]);
+ mAllAppsList.addPackage(context, packages[i]);
+ }
+ break;
+ case OP_UPDATE:
+ for (int i=0; i<N; i++) {
+ if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.updatePackage " + packages[i]);
+ mAllAppsList.updatePackage(context, packages[i]);
+ }
+ break;
+ case OP_REMOVE:
+ case OP_UNAVAILABLE:
+ for (int i=0; i<N; i++) {
+ if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.removePackage " + packages[i]);
+ mAllAppsList.removePackage(packages[i]);
+ }
+ break;
+ }
+
+ ArrayList<ApplicationInfo> added = null;
+ ArrayList<ApplicationInfo> removed = null;
+ ArrayList<ApplicationInfo> modified = null;
+
+ if (mAllAppsList.added.size() > 0) {
+ added = mAllAppsList.added;
+ mAllAppsList.added = new ArrayList<ApplicationInfo>();
+ }
+ if (mAllAppsList.removed.size() > 0) {
+ removed = mAllAppsList.removed;
+ mAllAppsList.removed = new ArrayList<ApplicationInfo>();
+ for (ApplicationInfo info: removed) {
+ mIconCache.remove(info.intent.getComponent());
+ }
+ }
+ if (mAllAppsList.modified.size() > 0) {
+ modified = mAllAppsList.modified;
+ mAllAppsList.modified = new ArrayList<ApplicationInfo>();
+ }
+
+ final Callbacks callbacks = mCallbacks != null ? mCallbacks.get() : null;
+ if (callbacks == null) {
+ Log.w(TAG, "Nobody to tell about the new app. Launcher is probably loading.");
+ return;
+ }
+
+ if (added != null) {
+ final ArrayList<ApplicationInfo> addedFinal = added;
+ mHandler.post(new Runnable() {
+ public void run() {
+ if (callbacks == mCallbacks.get()) {
+ callbacks.bindAppsAdded(addedFinal);
+ }
+ }
+ });
+ }
+ if (modified != null) {
+ final ArrayList<ApplicationInfo> modifiedFinal = modified;
+ mHandler.post(new Runnable() {
+ public void run() {
+ if (callbacks == mCallbacks.get()) {
+ callbacks.bindAppsUpdated(modifiedFinal);
+ }
+ }
+ });
+ }
+ if (removed != null) {
+ final boolean permanent = mOp != OP_UNAVAILABLE;
+ final ArrayList<ApplicationInfo> removedFinal = removed;
+ mHandler.post(new Runnable() {
+ public void run() {
+ if (callbacks == mCallbacks.get()) {
+ callbacks.bindAppsRemoved(removedFinal, permanent);
+ }
+ }
+ });
}
}
}
@@ -1511,7 +1502,7 @@
// into the DB. We do this so when we're loading, if the
// package manager can't find an icon (for example because
// the app is on SD) then we can use that instead.
- if (info.onExternalStorage && !info.customIcon && !info.usingFallbackIcon) {
+ if (!info.customIcon && !info.usingFallbackIcon) {
boolean needSave;
byte[] data = c.getBlob(iconIndex);
try {
@@ -1585,12 +1576,16 @@
};
public void dumpState() {
- Log.d(TAG, "mBeforeFirstLoad=" + mBeforeFirstLoad);
Log.d(TAG, "mCallbacks=" + mCallbacks);
ApplicationInfo.dumpApplicationInfoList(TAG, "mAllAppsList.data", mAllAppsList.data);
ApplicationInfo.dumpApplicationInfoList(TAG, "mAllAppsList.added", mAllAppsList.added);
ApplicationInfo.dumpApplicationInfoList(TAG, "mAllAppsList.removed", mAllAppsList.removed);
ApplicationInfo.dumpApplicationInfoList(TAG, "mAllAppsList.modified", mAllAppsList.modified);
- mLoader.dumpState();
+ Log.d(TAG, "mItems size=" + mItems.size());
+ if (mLoaderTask != null) {
+ mLoaderTask.dumpState();
+ } else {
+ Log.d(TAG, "mLoaderTask=null");
+ }
}
}
diff --git a/src/com/android/launcher2/ShortcutInfo.java b/src/com/android/launcher2/ShortcutInfo.java
index 5c322ba..2c5aec4 100644
--- a/src/com/android/launcher2/ShortcutInfo.java
+++ b/src/com/android/launcher2/ShortcutInfo.java
@@ -54,11 +54,6 @@
boolean usingFallbackIcon;
/**
- * Indicates whether the shortcut is on external storage and may go away at any time.
- */
- boolean onExternalStorage;
-
- /**
* If isShortcut=true and customIcon=false, this contains a reference to the
* shortcut icon as an application's resource.
*/
@@ -101,6 +96,7 @@
public Bitmap getIcon(IconCache iconCache) {
if (mIcon == null) {
mIcon = iconCache.getIcon(this.intent);
+ this.usingFallbackIcon = iconCache.isDefaultIcon(mIcon);
}
return mIcon;
}
@@ -135,7 +131,7 @@
LauncherSettings.BaseLauncherColumns.ICON_TYPE_BITMAP);
writeBitmap(values, mIcon);
} else {
- if (onExternalStorage && !usingFallbackIcon) {
+ if (!usingFallbackIcon) {
writeBitmap(values, mIcon);
}
values.put(LauncherSettings.BaseLauncherColumns.ICON_TYPE,
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index c337c30..c182209 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -558,9 +558,7 @@
public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) {
int screen = indexOfChild(child);
if (screen != mCurrentScreen || !mScroller.isFinished()) {
- if (!mLauncher.isWorkspaceLocked()) {
- snapToScreen(screen);
- }
+ snapToScreen(screen);
return true;
}
return false;
@@ -625,7 +623,7 @@
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- if (mLauncher.isWorkspaceLocked() || mLauncher.isAllAppsVisible()) {
+ if (mLauncher.isAllAppsVisible()) {
return false;
}
}
@@ -634,9 +632,8 @@
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
- final boolean workspaceLocked = mLauncher.isWorkspaceLocked();
final boolean allAppsVisible = mLauncher.isAllAppsVisible();
- if (workspaceLocked || allAppsVisible) {
+ if (allAppsVisible) {
return false; // We don't want the events. Let them fall through to the all apps view.
}
@@ -656,10 +653,7 @@
return true;
}
- if (mVelocityTracker == null) {
- mVelocityTracker = VelocityTracker.obtain();
- }
- mVelocityTracker.addMovement(ev);
+ acquireVelocityTrackerAndAddMovement(ev);
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_MOVE: {
@@ -744,12 +738,7 @@
mTouchState = TOUCH_STATE_REST;
mActivePointerId = INVALID_POINTER;
mAllowLongPress = false;
-
- if (mVelocityTracker != null) {
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- }
-
+ releaseVelocityTracker();
break;
case MotionEvent.ACTION_POINTER_UP:
@@ -840,9 +829,6 @@
@Override
public boolean onTouchEvent(MotionEvent ev) {
- if (mLauncher.isWorkspaceLocked()) {
- return false; // We don't want the events. Let them fall through to the all apps view.
- }
if (mLauncher.isAllAppsVisible()) {
// Cancel any scrolling that is in progress.
if (!mScroller.isFinished()) {
@@ -852,10 +838,7 @@
return false; // We don't want the events. Let them fall through to the all apps view.
}
- if (mVelocityTracker == null) {
- mVelocityTracker = VelocityTracker.obtain();
- }
- mVelocityTracker.addMovement(ev);
+ acquireVelocityTrackerAndAddMovement(ev);
final int action = ev.getAction();
@@ -928,18 +911,20 @@
} else {
snapToScreen(whichScreen, 0, true);
}
-
- if (mVelocityTracker != null) {
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- }
}
mTouchState = TOUCH_STATE_REST;
mActivePointerId = INVALID_POINTER;
+ releaseVelocityTracker();
break;
case MotionEvent.ACTION_CANCEL:
+ if (mTouchState == TOUCH_STATE_SCROLLING) {
+ final int screenWidth = getWidth();
+ final int whichScreen = (mScrollX + (screenWidth / 2)) / screenWidth;
+ snapToScreen(whichScreen, 0, true);
+ }
mTouchState = TOUCH_STATE_REST;
mActivePointerId = INVALID_POINTER;
+ releaseVelocityTracker();
break;
case MotionEvent.ACTION_POINTER_UP:
onSecondaryPointerUp(ev);
@@ -949,6 +934,20 @@
return true;
}
+ private void acquireVelocityTrackerAndAddMovement(MotionEvent ev) {
+ if (mVelocityTracker == null) {
+ mVelocityTracker = VelocityTracker.obtain();
+ }
+ mVelocityTracker.addMovement(ev);
+ }
+
+ private void releaseVelocityTracker() {
+ if (mVelocityTracker != null) {
+ mVelocityTracker.recycle();
+ mVelocityTracker = null;
+ }
+ }
+
void snapToScreen(int whichScreen) {
snapToScreen(whichScreen, 0, false);
}
@@ -1351,7 +1350,6 @@
if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
for (String packageName: packageNames) {
if (packageName.equals(name.getPackageName())) {
- // TODO: This should probably be done on a worker thread
LauncherModel.deleteItemFromDatabase(mLauncher, info);
childrenToRemove.add(view);
}
@@ -1373,9 +1371,7 @@
for (String packageName: packageNames) {
if (packageName.equals(name.getPackageName())) {
toRemove.add(appInfo);
- // TODO: This should probably be done on a worker thread
- LauncherModel.deleteItemFromDatabase(
- mLauncher, appInfo);
+ LauncherModel.deleteItemFromDatabase(mLauncher, appInfo);
removedFromFolder = true;
}
}
@@ -1396,7 +1392,6 @@
if (providerInfo != null) {
for (String packageName: packageNames) {
if (packageName.equals(providerInfo.packageName)) {
- // TODO: This should probably be done on a worker thread
LauncherModel.deleteItemFromDatabase(mLauncher, info);
childrenToRemove.add(view);
}
@@ -1409,7 +1404,6 @@
if (provider != null) {
for (String packageName: packageNames) {
if (packageName.equals(provider.provider.getPackageName())) {
- // TODO: This should probably be done on a worker thread
LauncherModel.deleteItemFromDatabase(mLauncher, info);
childrenToRemove.add(view);
}