summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--res/drawable-land/delete_handle.pngbin2104 -> 859 bytes
-rw-r--r--res/drawable-land/delete_handle_normal.pngbin2768 -> 3587 bytes
-rw-r--r--res/drawable-land/ic_delete.pngbin1445 -> 651 bytes
-rw-r--r--res/drawable-land/ic_tray_collapse.pngbin1333 -> 1229 bytes
-rw-r--r--res/drawable-land/ic_tray_expand.pngbin1324 -> 1225 bytes
-rw-r--r--res/drawable-land/tray_handle_normal.pngbin1420 -> 5811 bytes
-rw-r--r--res/drawable-land/tray_handle_pressed.pngbin2354 -> 1792 bytes
-rw-r--r--res/drawable-land/tray_handle_selected.pngbin2451 -> 1828 bytes
-rw-r--r--res/drawable-port/delete_handle.pngbin2135 -> 982 bytes
-rw-r--r--res/drawable-port/delete_handle_normal.pngbin2976 -> 3249 bytes
-rw-r--r--res/drawable-port/ic_delete.pngbin1441 -> 646 bytes
-rw-r--r--res/drawable-port/ic_tray_collapse.pngbin1112 -> 1182 bytes
-rw-r--r--res/drawable-port/ic_tray_expand.pngbin1101 -> 1190 bytes
-rw-r--r--res/drawable-port/tray_handle_normal.pngbin1615 -> 5261 bytes
-rw-r--r--res/drawable-port/tray_handle_pressed.pngbin2470 -> 1649 bytes
-rw-r--r--res/drawable-port/tray_handle_selected.pngbin2529 -> 1672 bytes
-rwxr-xr-xres/drawable/box_launcher_bottom.9.pngbin962 -> 833 bytes
-rw-r--r--res/drawable/box_launcher_top_normal.9.pngbin1388 -> 1685 bytes
-rw-r--r--res/drawable/box_launcher_top_pressed.9.pngbin1786 -> 2023 bytes
-rw-r--r--res/drawable/box_launcher_top_selected.9.pngbin1821 -> 2033 bytes
-rw-r--r--res/drawable/pattern_carbon_fiber_dark.pngbin0 -> 419 bytes
-rw-r--r--res/drawable/texture_brushed_steel.pngbin6726 -> 0 bytes
-rw-r--r--res/drawable/wallpaper_dale_chihuly.jpg0
-rw-r--r--res/drawable/wallpaper_dale_chihuly_small.jpg0
-rw-r--r--res/drawable/wallpaper_john_maeda.jpg0
-rw-r--r--res/drawable/wallpaper_john_maeda_small.jpg0
-rw-r--r--res/drawable/wallpaper_marc_ecko.jpg0
-rw-r--r--res/drawable/wallpaper_marc_ecko_small.jpg0
-rw-r--r--res/layout-land/launcher.xml2
-rw-r--r--res/layout-port/launcher.xml2
-rw-r--r--res/values/attrs.xml8
-rw-r--r--res/xml/default_workspace.xml71
-rw-r--r--src/com/android/launcher/AddAdapter.java6
-rw-r--r--src/com/android/launcher/Launcher.java127
-rw-r--r--src/com/android/launcher/LauncherModel.java370
-rw-r--r--src/com/android/launcher/LauncherProvider.java185
-rw-r--r--src/com/android/launcher/Workspace.java38
37 files changed, 638 insertions, 171 deletions
diff --git a/res/drawable-land/delete_handle.png b/res/drawable-land/delete_handle.png
index 5784c26fe..43a908170 100644
--- a/res/drawable-land/delete_handle.png
+++ b/res/drawable-land/delete_handle.png
Binary files differ
diff --git a/res/drawable-land/delete_handle_normal.png b/res/drawable-land/delete_handle_normal.png
index d3a8dbaf7..bc11ff8af 100644
--- a/res/drawable-land/delete_handle_normal.png
+++ b/res/drawable-land/delete_handle_normal.png
Binary files differ
diff --git a/res/drawable-land/ic_delete.png b/res/drawable-land/ic_delete.png
index 58871fdad..7b0f768c4 100644
--- a/res/drawable-land/ic_delete.png
+++ b/res/drawable-land/ic_delete.png
Binary files differ
diff --git a/res/drawable-land/ic_tray_collapse.png b/res/drawable-land/ic_tray_collapse.png
index 15c625748..c11f8b3f9 100644
--- a/res/drawable-land/ic_tray_collapse.png
+++ b/res/drawable-land/ic_tray_collapse.png
Binary files differ
diff --git a/res/drawable-land/ic_tray_expand.png b/res/drawable-land/ic_tray_expand.png
index 38836af7c..cd3e5a464 100644
--- a/res/drawable-land/ic_tray_expand.png
+++ b/res/drawable-land/ic_tray_expand.png
Binary files differ
diff --git a/res/drawable-land/tray_handle_normal.png b/res/drawable-land/tray_handle_normal.png
index 93b85976f..0cd214651 100644
--- a/res/drawable-land/tray_handle_normal.png
+++ b/res/drawable-land/tray_handle_normal.png
Binary files differ
diff --git a/res/drawable-land/tray_handle_pressed.png b/res/drawable-land/tray_handle_pressed.png
index e2cae0e82..c875617b1 100644
--- a/res/drawable-land/tray_handle_pressed.png
+++ b/res/drawable-land/tray_handle_pressed.png
Binary files differ
diff --git a/res/drawable-land/tray_handle_selected.png b/res/drawable-land/tray_handle_selected.png
index 106c8f41e..1dfdf1ece 100644
--- a/res/drawable-land/tray_handle_selected.png
+++ b/res/drawable-land/tray_handle_selected.png
Binary files differ
diff --git a/res/drawable-port/delete_handle.png b/res/drawable-port/delete_handle.png
index 9ce092411..94a5cd0c0 100644
--- a/res/drawable-port/delete_handle.png
+++ b/res/drawable-port/delete_handle.png
Binary files differ
diff --git a/res/drawable-port/delete_handle_normal.png b/res/drawable-port/delete_handle_normal.png
index 1f0a7acae..95b3da710 100644
--- a/res/drawable-port/delete_handle_normal.png
+++ b/res/drawable-port/delete_handle_normal.png
Binary files differ
diff --git a/res/drawable-port/ic_delete.png b/res/drawable-port/ic_delete.png
index 88330e75b..382cba974 100644
--- a/res/drawable-port/ic_delete.png
+++ b/res/drawable-port/ic_delete.png
Binary files differ
diff --git a/res/drawable-port/ic_tray_collapse.png b/res/drawable-port/ic_tray_collapse.png
index b6b8a77a7..712d18981 100644
--- a/res/drawable-port/ic_tray_collapse.png
+++ b/res/drawable-port/ic_tray_collapse.png
Binary files differ
diff --git a/res/drawable-port/ic_tray_expand.png b/res/drawable-port/ic_tray_expand.png
index d2bbbd0e7..753a4c9b2 100644
--- a/res/drawable-port/ic_tray_expand.png
+++ b/res/drawable-port/ic_tray_expand.png
Binary files differ
diff --git a/res/drawable-port/tray_handle_normal.png b/res/drawable-port/tray_handle_normal.png
index bf82049b0..e98964594 100644
--- a/res/drawable-port/tray_handle_normal.png
+++ b/res/drawable-port/tray_handle_normal.png
Binary files differ
diff --git a/res/drawable-port/tray_handle_pressed.png b/res/drawable-port/tray_handle_pressed.png
index b9d8e02d8..bc6e03f87 100644
--- a/res/drawable-port/tray_handle_pressed.png
+++ b/res/drawable-port/tray_handle_pressed.png
Binary files differ
diff --git a/res/drawable-port/tray_handle_selected.png b/res/drawable-port/tray_handle_selected.png
index 01c2522e4..b319c8db0 100644
--- a/res/drawable-port/tray_handle_selected.png
+++ b/res/drawable-port/tray_handle_selected.png
Binary files differ
diff --git a/res/drawable/box_launcher_bottom.9.png b/res/drawable/box_launcher_bottom.9.png
index f4cc1fa10..1c99c5047 100755
--- a/res/drawable/box_launcher_bottom.9.png
+++ b/res/drawable/box_launcher_bottom.9.png
Binary files differ
diff --git a/res/drawable/box_launcher_top_normal.9.png b/res/drawable/box_launcher_top_normal.9.png
index abaff9597..30b17b29f 100644
--- a/res/drawable/box_launcher_top_normal.9.png
+++ b/res/drawable/box_launcher_top_normal.9.png
Binary files differ
diff --git a/res/drawable/box_launcher_top_pressed.9.png b/res/drawable/box_launcher_top_pressed.9.png
index 4e163d427..033cd4897 100644
--- a/res/drawable/box_launcher_top_pressed.9.png
+++ b/res/drawable/box_launcher_top_pressed.9.png
Binary files differ
diff --git a/res/drawable/box_launcher_top_selected.9.png b/res/drawable/box_launcher_top_selected.9.png
index 01b1c4e1e..3ef394c09 100644
--- a/res/drawable/box_launcher_top_selected.9.png
+++ b/res/drawable/box_launcher_top_selected.9.png
Binary files differ
diff --git a/res/drawable/pattern_carbon_fiber_dark.png b/res/drawable/pattern_carbon_fiber_dark.png
new file mode 100644
index 000000000..44e050f4c
--- /dev/null
+++ b/res/drawable/pattern_carbon_fiber_dark.png
Binary files differ
diff --git a/res/drawable/texture_brushed_steel.png b/res/drawable/texture_brushed_steel.png
deleted file mode 100644
index 73b3dfe63..000000000
--- a/res/drawable/texture_brushed_steel.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/wallpaper_dale_chihuly.jpg b/res/drawable/wallpaper_dale_chihuly.jpg
deleted file mode 100644
index e69de29bb..000000000
--- 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 e69de29bb..000000000
--- 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 e69de29bb..000000000
--- 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 e69de29bb..000000000
--- 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 e69de29bb..000000000
--- 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 e69de29bb..000000000
--- 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 2b262c37e..8214863f7 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 0c249a344..7dcacd6dd 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 ab545aa76..1fcad8160 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 000000000..fd7adf761
--- /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 cbcb3380a..996c619a9 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 17f16a7a3..50c785d08 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 70b4c10f4..de84560be 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 5cd7a0ff9..21ef1e0f1 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 bc5347e7a..359767aea 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() {
// }