diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-18 17:39:48 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-18 17:39:48 -0700 |
commit | f96811cdf564469a7a654a0c876288c9fd14f35e (patch) | |
tree | 5664248887a6270a5980a195ee9a8a9b3aecb588 | |
parent | ca9475f0403d9c0e843d5c189575068a386b2eb6 (diff) | |
download | packages_apps_trebuchet-f96811cdf564469a7a654a0c876288c9fd14f35e.zip packages_apps_trebuchet-f96811cdf564469a7a654a0c876288c9fd14f35e.tar.gz packages_apps_trebuchet-f96811cdf564469a7a654a0c876288c9fd14f35e.tar.bz2 |
auto import from //branches/cupcake_rel/...@140373
37 files changed, 638 insertions, 171 deletions
diff --git a/res/drawable-land/delete_handle.png b/res/drawable-land/delete_handle.png Binary files differindex 5784c26..43a9081 100644 --- a/res/drawable-land/delete_handle.png +++ b/res/drawable-land/delete_handle.png diff --git a/res/drawable-land/delete_handle_normal.png b/res/drawable-land/delete_handle_normal.png Binary files differindex d3a8dba..bc11ff8 100644 --- a/res/drawable-land/delete_handle_normal.png +++ b/res/drawable-land/delete_handle_normal.png diff --git a/res/drawable-land/ic_delete.png b/res/drawable-land/ic_delete.png Binary files differindex 58871fd..7b0f768 100644 --- a/res/drawable-land/ic_delete.png +++ b/res/drawable-land/ic_delete.png diff --git a/res/drawable-land/ic_tray_collapse.png b/res/drawable-land/ic_tray_collapse.png Binary files differindex 15c6257..c11f8b3 100644 --- a/res/drawable-land/ic_tray_collapse.png +++ b/res/drawable-land/ic_tray_collapse.png diff --git a/res/drawable-land/ic_tray_expand.png b/res/drawable-land/ic_tray_expand.png Binary files differindex 38836af..cd3e5a4 100644 --- a/res/drawable-land/ic_tray_expand.png +++ b/res/drawable-land/ic_tray_expand.png diff --git a/res/drawable-land/tray_handle_normal.png b/res/drawable-land/tray_handle_normal.png Binary files differindex 93b8597..0cd2146 100644 --- a/res/drawable-land/tray_handle_normal.png +++ b/res/drawable-land/tray_handle_normal.png diff --git a/res/drawable-land/tray_handle_pressed.png b/res/drawable-land/tray_handle_pressed.png Binary files differindex e2cae0e..c875617 100644 --- a/res/drawable-land/tray_handle_pressed.png +++ b/res/drawable-land/tray_handle_pressed.png diff --git a/res/drawable-land/tray_handle_selected.png b/res/drawable-land/tray_handle_selected.png Binary files differindex 106c8f4..1dfdf1e 100644 --- a/res/drawable-land/tray_handle_selected.png +++ b/res/drawable-land/tray_handle_selected.png diff --git a/res/drawable-port/delete_handle.png b/res/drawable-port/delete_handle.png Binary files differindex 9ce0924..94a5cd0 100644 --- a/res/drawable-port/delete_handle.png +++ b/res/drawable-port/delete_handle.png diff --git a/res/drawable-port/delete_handle_normal.png b/res/drawable-port/delete_handle_normal.png Binary files differindex 1f0a7ac..95b3da7 100644 --- a/res/drawable-port/delete_handle_normal.png +++ b/res/drawable-port/delete_handle_normal.png diff --git a/res/drawable-port/ic_delete.png b/res/drawable-port/ic_delete.png Binary files differindex 88330e7..382cba9 100644 --- a/res/drawable-port/ic_delete.png +++ b/res/drawable-port/ic_delete.png diff --git a/res/drawable-port/ic_tray_collapse.png b/res/drawable-port/ic_tray_collapse.png Binary files differindex b6b8a77..712d189 100644 --- a/res/drawable-port/ic_tray_collapse.png +++ b/res/drawable-port/ic_tray_collapse.png diff --git a/res/drawable-port/ic_tray_expand.png b/res/drawable-port/ic_tray_expand.png Binary files differindex d2bbbd0..753a4c9 100644 --- a/res/drawable-port/ic_tray_expand.png +++ b/res/drawable-port/ic_tray_expand.png diff --git a/res/drawable-port/tray_handle_normal.png b/res/drawable-port/tray_handle_normal.png Binary files differindex bf82049..e989645 100644 --- a/res/drawable-port/tray_handle_normal.png +++ b/res/drawable-port/tray_handle_normal.png diff --git a/res/drawable-port/tray_handle_pressed.png b/res/drawable-port/tray_handle_pressed.png Binary files differindex b9d8e02..bc6e03f 100644 --- a/res/drawable-port/tray_handle_pressed.png +++ b/res/drawable-port/tray_handle_pressed.png diff --git a/res/drawable-port/tray_handle_selected.png b/res/drawable-port/tray_handle_selected.png Binary files differindex 01c2522..b319c8d 100644 --- a/res/drawable-port/tray_handle_selected.png +++ b/res/drawable-port/tray_handle_selected.png diff --git a/res/drawable/box_launcher_bottom.9.png b/res/drawable/box_launcher_bottom.9.png Binary files differindex f4cc1fa..1c99c50 100755 --- a/res/drawable/box_launcher_bottom.9.png +++ b/res/drawable/box_launcher_bottom.9.png diff --git a/res/drawable/box_launcher_top_normal.9.png b/res/drawable/box_launcher_top_normal.9.png Binary files differindex abaff95..30b17b2 100644 --- a/res/drawable/box_launcher_top_normal.9.png +++ b/res/drawable/box_launcher_top_normal.9.png diff --git a/res/drawable/box_launcher_top_pressed.9.png b/res/drawable/box_launcher_top_pressed.9.png Binary files differindex 4e163d4..033cd48 100644 --- a/res/drawable/box_launcher_top_pressed.9.png +++ b/res/drawable/box_launcher_top_pressed.9.png diff --git a/res/drawable/box_launcher_top_selected.9.png b/res/drawable/box_launcher_top_selected.9.png Binary files differindex 01b1c4e..3ef394c 100644 --- a/res/drawable/box_launcher_top_selected.9.png +++ b/res/drawable/box_launcher_top_selected.9.png diff --git a/res/drawable/pattern_carbon_fiber_dark.png b/res/drawable/pattern_carbon_fiber_dark.png Binary files differnew file mode 100644 index 0000000..44e050f --- /dev/null +++ b/res/drawable/pattern_carbon_fiber_dark.png diff --git a/res/drawable/texture_brushed_steel.png b/res/drawable/texture_brushed_steel.png Binary files differdeleted file mode 100644 index 73b3dfe..0000000 --- a/res/drawable/texture_brushed_steel.png +++ /dev/null diff --git a/res/drawable/wallpaper_dale_chihuly.jpg b/res/drawable/wallpaper_dale_chihuly.jpg deleted file mode 100644 index e69de29..0000000 --- a/res/drawable/wallpaper_dale_chihuly.jpg +++ /dev/null diff --git a/res/drawable/wallpaper_dale_chihuly_small.jpg b/res/drawable/wallpaper_dale_chihuly_small.jpg deleted file mode 100644 index e69de29..0000000 --- a/res/drawable/wallpaper_dale_chihuly_small.jpg +++ /dev/null diff --git a/res/drawable/wallpaper_john_maeda.jpg b/res/drawable/wallpaper_john_maeda.jpg deleted file mode 100644 index e69de29..0000000 --- a/res/drawable/wallpaper_john_maeda.jpg +++ /dev/null diff --git a/res/drawable/wallpaper_john_maeda_small.jpg b/res/drawable/wallpaper_john_maeda_small.jpg deleted file mode 100644 index e69de29..0000000 --- a/res/drawable/wallpaper_john_maeda_small.jpg +++ /dev/null diff --git a/res/drawable/wallpaper_marc_ecko.jpg b/res/drawable/wallpaper_marc_ecko.jpg deleted file mode 100644 index e69de29..0000000 --- a/res/drawable/wallpaper_marc_ecko.jpg +++ /dev/null diff --git a/res/drawable/wallpaper_marc_ecko_small.jpg b/res/drawable/wallpaper_marc_ecko_small.jpg deleted file mode 100644 index e69de29..0000000 --- a/res/drawable/wallpaper_marc_ecko_small.jpg +++ /dev/null diff --git a/res/layout-land/launcher.xml b/res/layout-land/launcher.xml index 2b262c3..8214863 100644 --- a/res/layout-land/launcher.xml +++ b/res/layout-land/launcher.xml @@ -66,7 +66,7 @@ android:layout_width="fill_parent" android:layout_height="fill_parent" - launcher:texture="@drawable/texture_brushed_steel" + launcher:texture="@drawable/pattern_carbon_fiber_dark" android:scrollbarStyle="outsideInset" android:drawSelectorOnTop="false" diff --git a/res/layout-port/launcher.xml b/res/layout-port/launcher.xml index 0c249a3..7dcacd6 100644 --- a/res/layout-port/launcher.xml +++ b/res/layout-port/launcher.xml @@ -66,7 +66,7 @@ android:layout_width="fill_parent" android:layout_height="fill_parent" - launcher:texture="@drawable/texture_brushed_steel" + launcher:texture="@drawable/pattern_carbon_fiber_dark" android:scrollbarStyle="outsideInset" android:drawSelectorOnTop="false" diff --git a/res/values/attrs.xml b/res/values/attrs.xml index ab545aa..1fcad81 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -76,4 +76,12 @@ <attr name="texture" format="reference" /> </declare-styleable> + <!-- XML attributes used by default_workspace.xml --> + <declare-styleable name="Favorite"> + <attr name="className" format="string" /> + <attr name="packageName" format="string" /> + <attr name="screen" format="string" /> + <attr name="x" format="string" /> + <attr name="y" format="string" /> + </declare-styleable> </resources> diff --git a/res/xml/default_workspace.xml b/res/xml/default_workspace.xml new file mode 100644 index 0000000..fd7adf7 --- /dev/null +++ b/res/xml/default_workspace.xml @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2009 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<favorites xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"> + + <clock + launcher:screen="1" + launcher:x="1" + launcher:y="0" /> + + <search + launcher:screen="2" + launcher:x="0" + launcher:y="0" /> + + <favorite + launcher:packageName="com.android.contacts" + launcher:className="com.android.contacts.DialtactsActivity" + launcher:screen="1" + launcher:x="0" + launcher:y="3" /> + + <favorite + launcher:packageName="com.android.contacts" + launcher:className="com.android.contacts.DialtactsContactsEntryActivity" + launcher:screen="1" + launcher:x="1" + launcher:y="3" /> + + <favorite + launcher:packageName="com.android.browser" + launcher:className="com.android.browser.BrowserActivity" + launcher:screen="1" + launcher:x="2" + launcher:y="3" /> + + <favorite + launcher:packageName="com.google.android.apps.maps" + launcher:className="com.google.android.maps.MapsActivity" + launcher:screen="1" + launcher:x="3" + launcher:y="3" /> + + <favorite + launcher:packageName="com.android.mms" + launcher:className="com.android.mms.ui.ConversationList" + launcher:screen="1" + launcher:x="0" + launcher:y="2" /> + + <favorite + launcher:packageName="com.android.vending" + launcher:className="com.android.vending.AssetBrowserActivity" + launcher:screen="1" + launcher:x="3" + launcher:y="2" /> + +</favorites> diff --git a/src/com/android/launcher/AddAdapter.java b/src/com/android/launcher/AddAdapter.java index cbcb338..996c619 100644 --- a/src/com/android/launcher/AddAdapter.java +++ b/src/com/android/launcher/AddAdapter.java @@ -79,8 +79,10 @@ public class AddAdapter extends BaseAdapter { mItems.add(new ListItem(res, R.string.group_shortcuts, R.drawable.ic_launcher_empty, ITEM_SHORTCUT)); - mItems.add(new ListItem(res, R.string.group_search, - R.drawable.ic_search_widget, ITEM_SEARCH)); + if (false) { + mItems.add(new ListItem(res, R.string.group_search, + R.drawable.ic_search_widget, ITEM_SEARCH)); + } mItems.add(new ListItem(res, R.string.group_widgets, R.drawable.ic_launcher_appwidget, ITEM_APPWIDGET)); diff --git a/src/com/android/launcher/Launcher.java b/src/com/android/launcher/Launcher.java index 17f16a7..50c785d 100644 --- a/src/com/android/launcher/Launcher.java +++ b/src/com/android/launcher/Launcher.java @@ -57,6 +57,7 @@ import android.text.SpannableStringBuilder; import android.text.TextUtils; import android.text.method.TextKeyListener; import android.util.Log; +import static android.util.Log.*; import android.view.Display; import android.view.Gravity; import android.view.KeyEvent; @@ -112,6 +113,9 @@ public final class Launcher extends Activity implements View.OnClickListener, On static final String EXTRA_SHORTCUT_DUPLICATE = "duplicate"; + static final String EXTRA_CUSTOM_WIDGET = "custom_widget"; + static final String SEARCH_WIDGET = "search_widget"; + static final int SCREEN_COUNT = 3; static final int DEFAULT_SCREN = 1; static final int NUMBER_CELLS_X = 4; @@ -603,7 +607,7 @@ public final class Launcher extends Activity implements View.OnClickListener, On Bundle extras = data.getExtras(); int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, -1); - Log.d(LOG_TAG, "dumping extras content="+extras.toString()); + d(LOG_TAG, "dumping extras content="+extras.toString()); AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId); @@ -671,7 +675,7 @@ public final class Launcher extends Activity implements View.OnClickListener, On final int id = resources.getIdentifier(iconResource.resourceName, null, null); icon = resources.getDrawable(id); } catch (Exception e) { - Log.w(LOG_TAG, "Could not load shortcut icon: " + extra); + w(LOG_TAG, "Could not load shortcut icon: " + extra); } } } @@ -794,7 +798,7 @@ public final class Launcher extends Activity implements View.OnClickListener, On try { mAppWidgetHost.stopListening(); } catch (NullPointerException ex) { - Log.w(LOG_TAG, "problem while stopping AppWidgetHost during Launcher destruction", ex); + w(LOG_TAG, "problem while stopping AppWidgetHost during Launcher destruction", ex); } TextKeyListener.getInstance().release(); @@ -903,21 +907,36 @@ public final class Launcher extends Activity implements View.OnClickListener, On } } + private void updateShortcutsForPackage(String packageName) { + if (packageName != null && packageName.length() > 0) { + mWorkspace.updateShortcutsForPackage(packageName); + } + } + void addAppWidget(Intent data) { // TODO: catch bad widget exception when sent int appWidgetId = data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1); - AppWidgetProviderInfo appWidget = mAppWidgetManager.getAppWidgetInfo(appWidgetId); - if (appWidget.configure != null) { - // Launch over to configure widget, if needed - Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE); - intent.setComponent(appWidget.configure); - intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); - - startActivityForResult(intent, REQUEST_CREATE_APPWIDGET); + String customWidget = data.getStringExtra(EXTRA_CUSTOM_WIDGET); + if (SEARCH_WIDGET.equals(customWidget)) { + // We don't need this any more, since this isn't a real app widget. + mAppWidgetHost.deleteAppWidgetId(appWidgetId); + // add the search widget + addSearch(); } else { - // Otherwise just add it - onActivityResult(REQUEST_CREATE_APPWIDGET, Activity.RESULT_OK, data); + AppWidgetProviderInfo appWidget = mAppWidgetManager.getAppWidgetInfo(appWidgetId); + + if (appWidget.configure != null) { + // Launch over to configure widget, if needed + Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE); + intent.setComponent(appWidget.configure); + intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); + + startActivityForResult(intent, REQUEST_CREATE_APPWIDGET); + } else { + // Otherwise just add it + onActivityResult(REQUEST_CREATE_APPWIDGET, Activity.RESULT_OK, data); + } } } @@ -1008,7 +1027,7 @@ public final class Launcher extends Activity implements View.OnClickListener, On final int id = resources.getIdentifier(iconResource.resourceName, null, null); icon = resources.getDrawable(id); } catch (Exception e) { - Log.w(LOG_TAG, "Could not load live folder icon: " + extra); + w(LOG_TAG, "Could not load live folder icon: " + extra); } } @@ -1107,8 +1126,11 @@ public final class Launcher extends Activity implements View.OnClickListener, On switch (event.getKeyCode()) { case KeyEvent.KEYCODE_BACK: mWorkspace.dispatchKeyEvent(event); - closeFolder(); - closeDrawer(); + if (mDrawer.isOpened()) { + closeDrawer(); + } else { + closeFolder(); + } return true; case KeyEvent.KEYCODE_HOME: return true; @@ -1163,7 +1185,7 @@ public final class Launcher extends Activity implements View.OnClickListener, On void onDesktopItemsLoaded() { if (mDestroyed) return; -android.util.Log.d("Home", "setting grid adapter"); +d("Home", "setting grid adapter"); mAllAppsGrid.setAdapter(sModel.getApplicationsAdapter()); bindDesktopItems(); } @@ -1313,7 +1335,7 @@ android.util.Log.d("Home", "setting grid adapter"); final AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId); item.hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo); - if (LOGD) Log.d(LOG_TAG, String.format("about to setAppWidget for id=%d, info=%s", appWidgetId, appWidgetInfo)); + if (LOGD) d(LOG_TAG, String.format("about to setAppWidget for id=%d, info=%s", appWidgetId, appWidgetInfo)); item.hostView.setAppWidget(appWidgetId, appWidgetInfo); item.hostView.setTag(item); @@ -1704,6 +1726,23 @@ android.util.Log.d("Home", "setting grid adapter"); Intent pickIntent = new Intent(AppWidgetManager.ACTION_APPWIDGET_PICK); pickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); + // add the search widget + ArrayList<AppWidgetProviderInfo> customInfo = + new ArrayList<AppWidgetProviderInfo>(); + AppWidgetProviderInfo info = new AppWidgetProviderInfo(); + info.provider = new ComponentName(getPackageName(), "XXX.YYY"); + info.label = getString(R.string.group_search); + info.icon = R.drawable.ic_search_widget; + customInfo.add(info); + pickIntent.putParcelableArrayListExtra( + AppWidgetManager.EXTRA_CUSTOM_INFO, customInfo); + ArrayList<Bundle> customExtras = new ArrayList<Bundle>(); + Bundle b = new Bundle(); + b.putString(EXTRA_CUSTOM_WIDGET, SEARCH_WIDGET); + customExtras.add(b); + pickIntent.putParcelableArrayListExtra( + AppWidgetManager.EXTRA_CUSTOM_EXTRAS, customExtras); + // start the pick activity startActivityForResult(pickIntent, REQUEST_PICK_APPWIDGET); break; } @@ -1742,23 +1781,47 @@ android.util.Log.d("Home", "setting grid adapter"); private class ApplicationsIntentReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - boolean reloadWorkspace = false; -android.util.Log.d("Home", "application intent received: " + intent.getAction()); -android.util.Log.d("Home", " --> " + intent.getData()); - if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) { - if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) { - removeShortcutsForPackage(intent.getData().getSchemeSpecificPart()); + final String action = intent.getAction(); + final String packageName = intent.getData().getSchemeSpecificPart(); + final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false); + + if (LauncherModel.DEBUG_LOADERS) { + d(LauncherModel.LOG_TAG, "application intent received: " + action + + ", replacing=" + replacing); + d(LauncherModel.LOG_TAG, " --> " + intent.getData()); + } + + if (!Intent.ACTION_PACKAGE_CHANGED.equals(action)) { + if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) { + if (!replacing) { + removeShortcutsForPackage(packageName); + if (LauncherModel.DEBUG_LOADERS) { + d(LauncherModel.LOG_TAG, " --> remove package"); + } + sModel.removePackage(Launcher.this, packageName); + } + // else, we are replacing the package, so a PACKAGE_ADDED will be sent + // later, we will update the package at this time } else { - reloadWorkspace = true; + if (!replacing) { + if (LauncherModel.DEBUG_LOADERS) { + d(LauncherModel.LOG_TAG, " --> add package"); + } + sModel.addPackage(Launcher.this, packageName); + } else { + if (LauncherModel.DEBUG_LOADERS) { + d(LauncherModel.LOG_TAG, " --> update package " + packageName); + } + sModel.updatePackage(Launcher.this, packageName); + updateShortcutsForPackage(packageName); + } } - } - removeDialog(DIALOG_CREATE_SHORTCUT); - if (!reloadWorkspace) { -android.util.Log.d("Home", " --> loading apps"); - sModel.loadApplications(false, Launcher.this, false); + removeDialog(DIALOG_CREATE_SHORTCUT); } else { -android.util.Log.d("Home", " --> loading workspace"); - sModel.loadUserItems(false, Launcher.this, false, true); + if (LauncherModel.DEBUG_LOADERS) { + d(LauncherModel.LOG_TAG, " --> sync package " + packageName); + } + sModel.syncPackage(Launcher.this, packageName); } } } diff --git a/src/com/android/launcher/LauncherModel.java b/src/com/android/launcher/LauncherModel.java index 70b4c10..de84560 100644 --- a/src/com/android/launcher/LauncherModel.java +++ b/src/com/android/launcher/LauncherModel.java @@ -28,8 +28,9 @@ import android.content.res.Resources; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.drawable.Drawable; import android.net.Uri; -import android.util.Log; +import static android.util.Log.*; import android.os.Process; import java.util.ArrayList; @@ -46,13 +47,14 @@ import java.net.URISyntaxException; * for the Launcher. */ public class LauncherModel { + static final boolean DEBUG_LOADERS = false; + static final String LOG_TAG = "HomeLoaders"; + private static final int UI_NOTIFICATION_RATE = 4; private static final int DEFAULT_APPLICATIONS_NUMBER = 42; private static final long APPLICATION_NOT_RESPONDING_TIMEOUT = 5000; private static final int INITIAL_ICON_CACHE_CAPACITY = 50; - private static final boolean DEBUG = false; - private static final Collator sCollator = Collator.getInstance(); private boolean mApplicationsLoaded; @@ -101,14 +103,16 @@ public class LauncherModel { */ synchronized boolean loadApplications(boolean isLaunching, Launcher launcher, boolean localeChanged) { -android.util.Log.d("Home", "load applications"); + + if (DEBUG_LOADERS) d(LOG_TAG, "load applications"); + if (isLaunching && mApplicationsLoaded && !localeChanged) { mApplicationsAdapter = new ApplicationsAdapter(launcher, mApplications); -android.util.Log.d("Home", " --> applications loaded, return"); + if (DEBUG_LOADERS) d(LOG_TAG, " --> applications loaded, return"); return false; } - waitForApplicationsLoader(); + stopAndWaitForApplicationsLoader(); if (localeChanged) { dropApplicationCache(); @@ -129,9 +133,9 @@ android.util.Log.d("Home", " --> applications loaded, return"); return true; } - private synchronized void waitForApplicationsLoader() { + private synchronized void stopAndWaitForApplicationsLoader() { if (mApplicationsLoader != null && mApplicationsLoader.isRunning()) { - android.util.Log.d("Home", " --> wait for applications loader"); + if (DEBUG_LOADERS) d(LOG_TAG, " --> wait for applications loader"); mApplicationsLoader.stop(); // Wait for the currently running thread to finish, this can take a little @@ -145,14 +149,310 @@ android.util.Log.d("Home", " --> applications loaded, return"); } private synchronized void startApplicationsLoader(Launcher launcher) { -android.util.Log.d("Home", " --> starting applications loader"); - waitForApplicationsLoader(); + if (DEBUG_LOADERS) d(LOG_TAG, " --> starting applications loader"); + + stopAndWaitForApplicationsLoader(); mApplicationsLoader = new ApplicationsLoader(launcher); mApplicationsLoaderThread = new Thread(mApplicationsLoader, "Applications Loader"); mApplicationsLoaderThread.start(); } + synchronized void addPackage(Launcher launcher, String packageName) { + if (mApplicationsLoader != null && mApplicationsLoader.isRunning()) { + startApplicationsLoader(launcher); + return; + } + + if (packageName != null && packageName.length() > 0) { + final PackageManager packageManager = launcher.getPackageManager(); + final List<ResolveInfo> matches = findActivitiesForPackage(packageManager, packageName); + + if (matches.size() > 0) { + final ApplicationsAdapter adapter = mApplicationsAdapter; + final HashMap<ComponentName, ApplicationInfo> cache = mAppInfoCache; + + for (ResolveInfo info : matches) { + adapter.setNotifyOnChange(false); + adapter.add(makeAndCacheApplicationInfo(packageManager, cache, info)); + } + + adapter.sort(new ApplicationInfoComparator()); + adapter.notifyDataSetChanged(); + } + } + } + + synchronized void removePackage(Launcher launcher, String packageName) { + if (mApplicationsLoader != null && mApplicationsLoader.isRunning()) { + dropApplicationCache(); // TODO: this could be optimized + startApplicationsLoader(launcher); + return; + } + + if (packageName != null && packageName.length() > 0) { + final ApplicationsAdapter adapter = mApplicationsAdapter; + + final List<ApplicationInfo> toRemove = new ArrayList<ApplicationInfo>(); + final int count = adapter.getCount(); + + for (int i = 0; i < count; i++) { + final ApplicationInfo applicationInfo = adapter.getItem(i); + final Intent intent = applicationInfo.intent; + final ComponentName component = intent.getComponent(); + if (packageName.equals(component.getPackageName())) { + toRemove.add(applicationInfo); + } + } + + final HashMap<ComponentName, ApplicationInfo> cache = mAppInfoCache; + for (ApplicationInfo info : toRemove) { + adapter.setNotifyOnChange(false); + adapter.remove(info); + cache.remove(info.intent.getComponent()); + } + + if (toRemove.size() > 0) { + adapter.sort(new ApplicationInfoComparator()); + adapter.notifyDataSetChanged(); + } + } + } + + synchronized void updatePackage(Launcher launcher, String packageName) { + if (mApplicationsLoader != null && mApplicationsLoader.isRunning()) { + startApplicationsLoader(launcher); + return; + } + + if (packageName != null && packageName.length() > 0) { + final PackageManager packageManager = launcher.getPackageManager(); + final ApplicationsAdapter adapter = mApplicationsAdapter; + + final List<ResolveInfo> matches = findActivitiesForPackage(packageManager, packageName); + final int count = matches.size(); + + boolean changed = false; + + for (int i = 0; i < count; i++) { + final ResolveInfo info = matches.get(i); + final ApplicationInfo applicationInfo = findIntent(adapter, + info.activityInfo.applicationInfo.packageName, info.activityInfo.name); + if (applicationInfo != null) { + updateAndCacheApplicationInfo(packageManager, info, applicationInfo); + changed = true; + } + } + + if (changed) { + adapter.sort(new ApplicationInfoComparator()); + adapter.notifyDataSetChanged(); + } + } + } + + private void updateAndCacheApplicationInfo(PackageManager packageManager, ResolveInfo info, + ApplicationInfo applicationInfo) { + + updateApplicationInfoTitleAndIcon(packageManager, info, applicationInfo); + + ComponentName componentName = new ComponentName( + info.activityInfo.applicationInfo.packageName, info.activityInfo.name); + mAppInfoCache.put(componentName, applicationInfo); + } + + synchronized void syncPackage(Launcher launcher, String packageName) { + if (mApplicationsLoader != null && mApplicationsLoader.isRunning()) { + startApplicationsLoader(launcher); + return; + } + + if (packageName != null && packageName.length() > 0) { + final PackageManager packageManager = launcher.getPackageManager(); + final List<ResolveInfo> matches = findActivitiesForPackage(packageManager, packageName); + + if (matches.size() > 0) { + final ApplicationsAdapter adapter = mApplicationsAdapter; + + // Find disabled activities and remove them from the adapter + boolean removed = removeDisabledActivities(packageName, matches, adapter); + // Find enable activities and add them to the adapter + // Also updates existing activities with new labels/icons + boolean added = addEnabledAndUpdateActivities(matches, adapter, launcher); + + if (added || removed) { + adapter.sort(new ApplicationInfoComparator()); + adapter.notifyDataSetChanged(); + } + } + } + } + + private static List<ResolveInfo> findActivitiesForPackage(PackageManager packageManager, + String packageName) { + + final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); + mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); + + 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; + } + + private boolean addEnabledAndUpdateActivities(List<ResolveInfo> matches, + ApplicationsAdapter adapter, Launcher launcher) { + + final List<ApplicationInfo> toAdd = new ArrayList<ApplicationInfo>(); + final int count = matches.size(); + + boolean changed = false; + + for (int i = 0; i < count; i++) { + final ResolveInfo info = matches.get(i); + final ApplicationInfo applicationInfo = findIntent(adapter, + info.activityInfo.applicationInfo.packageName, info.activityInfo.name); + if (applicationInfo == null) { + toAdd.add(makeAndCacheApplicationInfo(launcher.getPackageManager(), + mAppInfoCache, info)); + changed = true; + } else { + updateAndCacheApplicationInfo(launcher.getPackageManager(), info, applicationInfo); + changed = true; + } + } + + for (ApplicationInfo info : toAdd) { + adapter.setNotifyOnChange(false); + adapter.add(info); + } + + return changed; + } + + private boolean removeDisabledActivities(String packageName, List<ResolveInfo> matches, + ApplicationsAdapter adapter) { + + final List<ApplicationInfo> toRemove = new ArrayList<ApplicationInfo>(); + final int count = adapter.getCount(); + + boolean changed = false; + + for (int i = 0; i < count; i++) { + final ApplicationInfo applicationInfo = adapter.getItem(i); + final Intent intent = applicationInfo.intent; + final ComponentName component = intent.getComponent(); + if (packageName.equals(component.getPackageName())) { + if (!findIntent(matches, component)) { + toRemove.add(applicationInfo); + changed = true; + } + } + } + + final HashMap<ComponentName, ApplicationInfo> cache = mAppInfoCache; + for (ApplicationInfo info : toRemove) { + adapter.setNotifyOnChange(false); + adapter.remove(info); + cache.remove(info.intent.getComponent()); + } + + return changed; + } + + private static ApplicationInfo findIntent(ApplicationsAdapter adapter, String packageName, + String name) { + + final int count = adapter.getCount(); + for (int i = 0; i < count; i++) { + final ApplicationInfo applicationInfo = adapter.getItem(i); + final Intent intent = applicationInfo.intent; + final ComponentName component = intent.getComponent(); + if (packageName.equals(component.getPackageName()) && + name.equals(component.getClassName())) { + return applicationInfo; + } + } + + return null; + } + + private static boolean findIntent(List<ResolveInfo> apps, ComponentName component) { + final String className = component.getClassName(); + for (ResolveInfo info : apps) { + final ActivityInfo activityInfo = info.activityInfo; + if (activityInfo.name.equals(className)) { + return true; + } + } + return false; + } + + Drawable getApplicationInfoIcon(PackageManager manager, ApplicationInfo info) { + final ResolveInfo resolveInfo = manager.resolveActivity(info.intent, 0); + if (resolveInfo == null) { + return null; + } + + ComponentName componentName = new ComponentName( + resolveInfo.activityInfo.applicationInfo.packageName, + resolveInfo.activityInfo.name); + ApplicationInfo application = mAppInfoCache.get(componentName); + + if (application == null) { + return resolveInfo.activityInfo.loadIcon(manager); + } + + return application.icon; + } + + private static ApplicationInfo makeAndCacheApplicationInfo(PackageManager manager, + HashMap<ComponentName, ApplicationInfo> appInfoCache, ResolveInfo info) { + + ComponentName componentName = new ComponentName( + info.activityInfo.applicationInfo.packageName, + info.activityInfo.name); + ApplicationInfo application = appInfoCache.get(componentName); + + if (application == null) { + application = new ApplicationInfo(); + application.container = ItemInfo.NO_ID; + + updateApplicationInfoTitleAndIcon(manager, info, application); + + application.setActivity(componentName, + Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); + + appInfoCache.put(componentName, application); + } + + return application; + } + + private static void updateApplicationInfoTitleAndIcon(PackageManager manager, ResolveInfo info, + ApplicationInfo application) { + + application.title = info.loadLabel(manager); + if (application.title == null) { + application.title = info.activityInfo.name; + } + + application.icon = info.activityInfo.loadIcon(manager); + application.filtered = false; + } + private class ApplicationsLoader implements Runnable { private final WeakReference<Launcher> mLauncher; @@ -176,7 +476,7 @@ android.util.Log.d("Home", " --> starting applications loader"); android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); - Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); + final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); final Launcher launcher = mLauncher.get(); @@ -185,6 +485,8 @@ android.util.Log.d("Home", " --> starting applications loader"); if (apps != null && !mStopped) { final int count = apps.size(); + // Can be set to null on the UI thread by the unbind() method + // Do not access without checking for null first final ApplicationsAdapter applicationList = mApplicationsAdapter; ChangeNotifier action = new ChangeNotifier(applicationList, true); @@ -192,28 +494,10 @@ android.util.Log.d("Home", " --> starting applications loader"); for (int i = 0; i < count && !mStopped; i++) { ResolveInfo info = apps.get(i); - ComponentName componentName = new ComponentName( - info.activityInfo.applicationInfo.packageName, - info.activityInfo.name); - ApplicationInfo application = appInfoCache.get(componentName); - if (application == null) { - application = new ApplicationInfo(); - application.title = info.loadLabel(manager); - if (application.title == null) { - application.title = info.activityInfo.name; - } - application.setActivity(componentName, - Intent.FLAG_ACTIVITY_NEW_TASK | - Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); - application.container = ItemInfo.NO_ID; - application.icon = info.activityInfo.loadIcon(manager); - if (DEBUG) { - Log.d(Launcher.LOG_TAG, "Loaded ApplicationInfo for " + componentName); - } - appInfoCache.put(componentName, application); - } + ApplicationInfo application = + makeAndCacheApplicationInfo(manager, appInfoCache, info); - if (action.add(application)) { + if (action.add(application) && !mStopped) { launcher.runOnUiThread(action); action = new ChangeNotifier(applicationList, false); } @@ -229,7 +513,7 @@ android.util.Log.d("Home", " --> starting applications loader"); } } - private static class ChangeNotifier implements Runnable, Comparator<ApplicationInfo> { + private static class ChangeNotifier implements Runnable { private final ApplicationsAdapter mApplicationList; private final ArrayList<ApplicationInfo> mBuffer; @@ -243,6 +527,8 @@ android.util.Log.d("Home", " --> starting applications loader"); public void run() { final ApplicationsAdapter applicationList = mApplicationList; + // Can be set to null on the UI thread by the unbind() method + if (applicationList == null) return; if (mFirst) { applicationList.setNotifyOnChange(false); @@ -260,7 +546,7 @@ android.util.Log.d("Home", " --> starting applications loader"); buffer.clear(); - applicationList.sort(this); + applicationList.sort(new ApplicationInfoComparator()); applicationList.notifyDataSetChanged(); } @@ -269,7 +555,9 @@ android.util.Log.d("Home", " --> starting applications loader"); buffer.add(application); return buffer.size() >= UI_NOTIFICATION_RATE; } + } + private static class ApplicationInfoComparator implements Comparator<ApplicationInfo> { public final int compare(ApplicationInfo a, ApplicationInfo b) { return sCollator.compare(a.title.toString(), b.title.toString()); } @@ -285,10 +573,10 @@ android.util.Log.d("Home", " --> starting applications loader"); */ void loadUserItems(boolean isLaunching, Launcher launcher, boolean localeChanged, boolean loadApplications) { -android.util.Log.d("Home", "loading user items"); + if (DEBUG_LOADERS) d(LOG_TAG, "loading user items"); if (isLaunching && isDesktopLoaded()) { -android.util.Log.d("Home", " --> items loaded, return"); + if (DEBUG_LOADERS) d(LOG_TAG, " --> items loaded, return"); if (loadApplications) startApplicationsLoader(launcher); // We have already loaded our data from the DB launcher.onDesktopItemsLoaded(); @@ -306,7 +594,7 @@ android.util.Log.d("Home", " --> items loaded, return"); } } -android.util.Log.d("Home", " --> starting workspace loader"); + if (DEBUG_LOADERS) d(LOG_TAG, " --> starting workspace loader"); mDesktopItemsLoaded = false; mDesktopItemsLoader = new DesktopItemsLoader(launcher, localeChanged, loadApplications); mDesktopLoaderThread = new Thread(mDesktopItemsLoader, "Desktop Items Loader"); @@ -563,7 +851,7 @@ android.util.Log.d("Home", " --> starting workspace loader"); container = c.getInt(containerIndex); if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP) { - Log.e(Launcher.LOG_TAG, "Widget found where container " + e(Launcher.LOG_TAG, "Widget found where container " + "!= CONTAINER_DESKTOP ignoring!"); continue; } @@ -589,7 +877,7 @@ android.util.Log.d("Home", " --> starting workspace loader"); container = c.getInt(containerIndex); if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP) { - Log.e(Launcher.LOG_TAG, "Widget found where container " + e(Launcher.LOG_TAG, "Widget found where container " + "!= CONTAINER_DESKTOP -- ignoring!"); continue; } @@ -599,7 +887,7 @@ android.util.Log.d("Home", " --> starting workspace loader"); break; } } catch (Exception e) { - Log.w(Launcher.LOG_TAG, "Desktop items loading interrupted:", e); + w(Launcher.LOG_TAG, "Desktop items loading interrupted:", e); } } } finally { @@ -699,6 +987,8 @@ android.util.Log.d("Home", " --> starting workspace loader"); * Home screen on orientation change. */ void unbind() { + // Interrupt the applications loader before setting the adapter to null + stopAndWaitForApplicationsLoader(); mApplicationsAdapter = null; unbindAppDrawables(mApplications); unbindDrawables(mDesktopItems); diff --git a/src/com/android/launcher/LauncherProvider.java b/src/com/android/launcher/LauncherProvider.java index 5cd7a0f..21ef1e0 100644 --- a/src/com/android/launcher/LauncherProvider.java +++ b/src/com/android/launcher/LauncherProvider.java @@ -24,6 +24,8 @@ import android.content.Intent; import android.content.ComponentName; import android.content.ContentUris; import android.content.ContentResolver; +import android.content.res.XmlResourceParser; +import android.content.res.TypedArray; import android.content.pm.PackageManager; import android.content.pm.ActivityInfo; import android.database.sqlite.SQLiteOpenHelper; @@ -33,19 +35,17 @@ import android.database.Cursor; import android.database.SQLException; import android.util.Log; import android.util.Xml; +import android.util.AttributeSet; import android.net.Uri; import android.text.TextUtils; import android.os.*; import android.provider.Settings; -import java.io.FileReader; -import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; -import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlPullParser; import com.android.internal.util.XmlUtils; import com.android.launcher.LauncherSettings.Favorites; @@ -162,19 +162,10 @@ public class LauncherProvider extends ContentProvider { } private static class DatabaseHelper extends SQLiteOpenHelper { - /** - * Path to file containing default favorite packages, relative to ANDROID_ROOT. - */ - private static final String DEFAULT_FAVORITES_PATH = "etc/favorites.xml"; - private static final String TAG_FAVORITES = "favorites"; private static final String TAG_FAVORITE = "favorite"; - private static final String TAG_PACKAGE = "package"; - private static final String TAG_CLASS = "class"; - - private static final String ATTRIBUTE_SCREEN = "screen"; - private static final String ATTRIBUTE_X = "x"; - private static final String ATTRIBUTE_Y = "y"; + private static final String TAG_CLOCK = "clock"; + private static final String TAG_SEARCH = "search"; private final Context mContext; private final AppWidgetHost mAppWidgetHost; @@ -217,7 +208,7 @@ public class LauncherProvider extends ContentProvider { if (!convertDatabase(db)) { // Populate favorites table with initial favorites - loadFavorites(db, DEFAULT_FAVORITES_PATH); + loadFavorites(db); } } @@ -445,115 +436,121 @@ public class LauncherProvider extends ContentProvider { * Loads the default set of favorite packages from an xml file. * * @param db The database to write the values into - * @param subPath The relative path from ANDROID_ROOT to the file to read */ - private int loadFavorites(SQLiteDatabase db, String subPath) { - FileReader favReader; - - // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system". - final File favFile = new File(Environment.getRootDirectory(), subPath); - try { - favReader = new FileReader(favFile); - } catch (FileNotFoundException e) { - Log.e(LOG_TAG, "Couldn't find or open favorites file " + favFile); - return 0; - } - + private int loadFavorites(SQLiteDatabase db) { Intent intent = new Intent(Intent.ACTION_MAIN, null); intent.addCategory(Intent.CATEGORY_LAUNCHER); ContentValues values = new ContentValues(); PackageManager packageManager = mContext.getPackageManager(); - ActivityInfo info; int i = 0; try { - XmlPullParser parser = Xml.newPullParser(); - parser.setInput(favReader); - + XmlResourceParser parser = mContext.getResources().getXml(R.xml.default_workspace); + AttributeSet attrs = Xml.asAttributeSet(parser); XmlUtils.beginDocument(parser, TAG_FAVORITES); - while (true) { - XmlUtils.nextElement(parser); + final int depth = parser.getDepth(); - String name = parser.getName(); - if (!TAG_FAVORITE.equals(name)) { - break; + int type; + while (((type = parser.next()) != XmlPullParser.END_TAG || + parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) { + + if (type != XmlPullParser.START_TAG) { + continue; } - String pkg = parser.getAttributeValue(null, TAG_PACKAGE); - String cls = parser.getAttributeValue(null, TAG_CLASS); - try { - ComponentName cn = new ComponentName(pkg, cls); - info = packageManager.getActivityInfo(cn, 0); - intent.setComponent(cn); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - values.put(LauncherSettings.Favorites.INTENT, intent.toURI()); - values.put(LauncherSettings.Favorites.TITLE, - info.loadLabel(packageManager).toString()); - values.put(LauncherSettings.Favorites.CONTAINER, - LauncherSettings.Favorites.CONTAINER_DESKTOP); - values.put(LauncherSettings.Favorites.ITEM_TYPE, - LauncherSettings.Favorites.ITEM_TYPE_APPLICATION); - values.put(LauncherSettings.Favorites.SCREEN, - parser.getAttributeValue(null, ATTRIBUTE_SCREEN)); - values.put(LauncherSettings.Favorites.CELLX, - parser.getAttributeValue(null, ATTRIBUTE_X)); - values.put(LauncherSettings.Favorites.CELLY, - parser.getAttributeValue(null, ATTRIBUTE_Y)); - values.put(LauncherSettings.Favorites.SPANX, 1); - values.put(LauncherSettings.Favorites.SPANY, 1); - db.insert(TABLE_FAVORITES, null, values); - i++; - } catch (PackageManager.NameNotFoundException e) { - Log.w(LOG_TAG, "Unable to add favorite: " + pkg + "/" + cls, e); + boolean added = false; + final String name = parser.getName(); + + TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.Favorite); + + values.clear(); + values.put(LauncherSettings.Favorites.CONTAINER, + LauncherSettings.Favorites.CONTAINER_DESKTOP); + values.put(LauncherSettings.Favorites.SCREEN, + a.getString(R.styleable.Favorite_screen)); + values.put(LauncherSettings.Favorites.CELLX, + a.getString(R.styleable.Favorite_x)); + values.put(LauncherSettings.Favorites.CELLY, + a.getString(R.styleable.Favorite_y)); + + if (TAG_FAVORITE.equals(name)) { + added = addShortcut(db, values, a, packageManager, intent); + } else if (TAG_SEARCH.equals(name)) { + added = addSearchWidget(db, values); + } else if (TAG_CLOCK.equals(name)) { + added = addClockWidget(db, values); } + + if (added) i++; + + a.recycle(); } } catch (XmlPullParserException e) { Log.w(LOG_TAG, "Got exception parsing favorites.", e); } catch (IOException e) { Log.w(LOG_TAG, "Got exception parsing favorites.", e); } - + + return i; + } + + private boolean addShortcut(SQLiteDatabase db, ContentValues values, TypedArray a, + PackageManager packageManager, Intent intent) { + + ActivityInfo info; + String packageName = a.getString(R.styleable.Favorite_packageName); + String className = a.getString(R.styleable.Favorite_className); + try { + ComponentName cn = new ComponentName(packageName, className); + info = packageManager.getActivityInfo(cn, 0); + intent.setComponent(cn); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + values.put(Favorites.INTENT, intent.toURI()); + values.put(Favorites.TITLE, info.loadLabel(packageManager).toString()); + values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_APPLICATION); + values.put(Favorites.SPANX, 1); + values.put(Favorites.SPANY, 1); + db.insert(TABLE_FAVORITES, null, values); + } catch (PackageManager.NameNotFoundException e) { + Log.w(LOG_TAG, "Unable to add favorite: " + packageName + + "/" + className, e); + return false; + } + return true; + } + + private boolean addSearchWidget(SQLiteDatabase db, ContentValues values) { // Add a search box - values.clear(); - values.put(LauncherSettings.Favorites.CONTAINER, - LauncherSettings.Favorites.CONTAINER_DESKTOP); - values.put(LauncherSettings.Favorites.ITEM_TYPE, - LauncherSettings.Favorites.ITEM_TYPE_WIDGET_SEARCH); - values.put(LauncherSettings.Favorites.SCREEN, 2); - values.put(LauncherSettings.Favorites.CELLX, 0); - values.put(LauncherSettings.Favorites.CELLY, 0); - values.put(LauncherSettings.Favorites.SPANX, 4); - values.put(LauncherSettings.Favorites.SPANY, 1); + values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_WIDGET_SEARCH); + values.put(Favorites.SPANX, 4); + values.put(Favorites.SPANY, 1); db.insert(TABLE_FAVORITES, null, values); - + + return true; + } + + private boolean addClockWidget(SQLiteDatabase db, ContentValues values) { final int[] bindSources = new int[] { Favorites.ITEM_TYPE_WIDGET_CLOCK, }; - + final ArrayList<ComponentName> bindTargets = new ArrayList<ComponentName>(); bindTargets.add(new ComponentName("com.android.alarmclock", "com.android.alarmclock.AnalogAppWidgetProvider")); - + boolean allocatedAppWidgets = false; - + // Try binding to an analog clock widget try { int appWidgetId = mAppWidgetHost.allocateAppWidgetId(); - - values.clear(); - values.put(LauncherSettings.Favorites.CONTAINER, - LauncherSettings.Favorites.CONTAINER_DESKTOP); - values.put(LauncherSettings.Favorites.ITEM_TYPE, - LauncherSettings.Favorites.ITEM_TYPE_WIDGET_CLOCK); - values.put(LauncherSettings.Favorites.SCREEN, 1); - values.put(LauncherSettings.Favorites.CELLX, 1); - values.put(LauncherSettings.Favorites.CELLY, 0); - values.put(LauncherSettings.Favorites.SPANX, 2); - values.put(LauncherSettings.Favorites.SPANY, 2); - values.put(LauncherSettings.Favorites.APPWIDGET_ID, appWidgetId); + + values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_WIDGET_CLOCK); + values.put(Favorites.SPANX, 2); + values.put(Favorites.SPANY, 2); + values.put(Favorites.APPWIDGET_ID, appWidgetId); db.insert(TABLE_FAVORITES, null, values); - + allocatedAppWidgets = true; } catch (RuntimeException ex) { Log.e(LOG_TAG, "Problem allocating appWidgetId", ex); @@ -563,8 +560,8 @@ public class LauncherProvider extends ContentProvider { if (allocatedAppWidgets) { launchAppWidgetBinder(bindSources, bindTargets); } - - return i; + + return allocatedAppWidgets; } } diff --git a/src/com/android/launcher/Workspace.java b/src/com/android/launcher/Workspace.java index bc5347e..359767a 100644 --- a/src/com/android/launcher/Workspace.java +++ b/src/com/android/launcher/Workspace.java @@ -26,6 +26,7 @@ import android.graphics.Paint; import android.graphics.RectF; import android.graphics.Rect; import android.graphics.Region; +import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.VelocityTracker; @@ -34,6 +35,7 @@ import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewParent; import android.widget.Scroller; +import android.widget.TextView; import android.os.Parcelable; import android.os.Parcel; @@ -1240,7 +1242,41 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag } } } - + + void updateShortcutsForPackage(String packageName) { + final int count = getChildCount(); + for (int i = 0; i < count; i++) { + final CellLayout layout = (CellLayout) getChildAt(i); + int childCount = layout.getChildCount(); + for (int j = 0; j < childCount; j++) { + final View view = layout.getChildAt(j); + Object tag = view.getTag(); + if (tag instanceof ApplicationInfo) { + ApplicationInfo info = (ApplicationInfo) tag; + // We need to check for ACTION_MAIN otherwise getComponent() might + // return null for some shortcuts (for instance, for shortcuts to + // web pages.) + final Intent intent = info.intent; + final ComponentName name = intent.getComponent(); + if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION && + Intent.ACTION_MAIN.equals(intent.getAction()) && name != null && + packageName.equals(name.getPackageName())) { + + final Drawable icon = Launcher.getModel().getApplicationInfoIcon( + mLauncher.getPackageManager(), info); + if (icon != null && icon != info.icon) { + info.icon.setCallback(null); + info.icon = Utilities.createIconThumbnail(icon, mContext); + info.filtered = true; + ((TextView) view).setCompoundDrawablesWithIntrinsicBounds(null, + info.icon, null, null); + } + } + } + } + } + } + // TODO: remove widgets when appwidgetmanager tells us they're gone // void removeAppWidgetsForProvider() { // } |