blob: 70b4c10f4ca73a6b000dcf3924029b1c32a2608e [file] [log] [blame]
The Android Open Source Project31dd5032009-03-03 19:32:27 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.launcher;
18
19import android.content.ComponentName;
20import android.content.ContentResolver;
21import android.content.ContentValues;
22import android.content.Intent;
23import android.content.Context;
24import android.content.pm.ActivityInfo;
25import android.content.pm.PackageManager;
26import android.content.pm.ResolveInfo;
27import android.content.res.Resources;
28import android.database.Cursor;
29import android.graphics.Bitmap;
30import android.graphics.BitmapFactory;
31import android.net.Uri;
32import android.util.Log;
33import android.os.Process;
34
35import java.util.ArrayList;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080036import java.util.HashMap;
37import java.util.List;
38import java.util.Comparator;
39import java.lang.ref.WeakReference;
40import java.text.Collator;
41import java.net.URISyntaxException;
42
43/**
44 * Maintains in-memory state of the Launcher. It is expected that there should be only one
45 * LauncherModel object held in a static. Also provide APIs for updating the database state
The Android Open Source Projectbc219c32009-03-09 11:52:14 -070046 * for the Launcher.
The Android Open Source Project31dd5032009-03-03 19:32:27 -080047 */
48public class LauncherModel {
49 private static final int UI_NOTIFICATION_RATE = 4;
50 private static final int DEFAULT_APPLICATIONS_NUMBER = 42;
51 private static final long APPLICATION_NOT_RESPONDING_TIMEOUT = 5000;
The Android Open Source Projectbc219c32009-03-09 11:52:14 -070052 private static final int INITIAL_ICON_CACHE_CAPACITY = 50;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080053
The Android Open Source Projectbc219c32009-03-09 11:52:14 -070054 private static final boolean DEBUG = false;
55
The Android Open Source Project7376fae2009-03-11 12:11:58 -070056 private static final Collator sCollator = Collator.getInstance();
The Android Open Source Project31dd5032009-03-03 19:32:27 -080057
58 private boolean mApplicationsLoaded;
59 private boolean mDesktopItemsLoaded;
60
61 private ArrayList<ItemInfo> mDesktopItems;
The Android Open Source Project7376fae2009-03-11 12:11:58 -070062 private ArrayList<LauncherAppWidgetInfo> mDesktopAppWidgets;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080063 private HashMap<Long, FolderInfo> mFolders;
64
65 private ArrayList<ApplicationInfo> mApplications;
66 private ApplicationsAdapter mApplicationsAdapter;
67 private ApplicationsLoader mApplicationsLoader;
68 private DesktopItemsLoader mDesktopItemsLoader;
The Android Open Source Projectca9475f2009-03-13 13:04:24 -070069 private Thread mApplicationsLoaderThread;
70 private Thread mDesktopLoaderThread;
The Android Open Source Project31dd5032009-03-03 19:32:27 -080071
The Android Open Source Projectbc219c32009-03-09 11:52:14 -070072 private final HashMap<ComponentName, ApplicationInfo> mAppInfoCache =
73 new HashMap<ComponentName, ApplicationInfo>(INITIAL_ICON_CACHE_CAPACITY);
74
The Android Open Source Projectca9475f2009-03-13 13:04:24 -070075 synchronized void abortLoaders() {
The Android Open Source Project31dd5032009-03-03 19:32:27 -080076 if (mApplicationsLoader != null && mApplicationsLoader.isRunning()) {
77 mApplicationsLoader.stop();
78 mApplicationsLoaded = false;
79 }
The Android Open Source Projectca9475f2009-03-13 13:04:24 -070080
The Android Open Source Project31dd5032009-03-03 19:32:27 -080081 if (mDesktopItemsLoader != null && mDesktopItemsLoader.isRunning()) {
82 mDesktopItemsLoader.stop();
83 mDesktopItemsLoaded = false;
84 }
85 }
86
87 /**
The Android Open Source Projectbc219c32009-03-09 11:52:14 -070088 * Drop our cache of components to their lables & icons. We do
89 * this from Launcher when applications are added/removed. It's a
90 * bit overkill, but it's a rare operation anyway.
91 */
92 synchronized void dropApplicationCache() {
93 mAppInfoCache.clear();
94 }
95
96 /**
The Android Open Source Project31dd5032009-03-03 19:32:27 -080097 * Loads the list of installed applications in mApplications.
The Android Open Source Projectca9475f2009-03-13 13:04:24 -070098 *
99 * @return true if the applications loader must be started
100 * (see startApplicationsLoader()), false otherwise.
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800101 */
The Android Open Source Projectca9475f2009-03-13 13:04:24 -0700102 synchronized boolean loadApplications(boolean isLaunching, Launcher launcher,
The Android Open Source Projectbc219c32009-03-09 11:52:14 -0700103 boolean localeChanged) {
The Android Open Source Projectca9475f2009-03-13 13:04:24 -0700104android.util.Log.d("Home", "load applications");
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800105 if (isLaunching && mApplicationsLoaded && !localeChanged) {
106 mApplicationsAdapter = new ApplicationsAdapter(launcher, mApplications);
The Android Open Source Projectca9475f2009-03-13 13:04:24 -0700107android.util.Log.d("Home", " --> applications loaded, return");
108 return false;
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800109 }
110
The Android Open Source Projectca9475f2009-03-13 13:04:24 -0700111 waitForApplicationsLoader();
112
113 if (localeChanged) {
114 dropApplicationCache();
115 }
116
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800117 if (mApplicationsAdapter == null || isLaunching || localeChanged) {
The Android Open Source Projectbc219c32009-03-09 11:52:14 -0700118 mApplications = new ArrayList<ApplicationInfo>(DEFAULT_APPLICATIONS_NUMBER);
119 mApplicationsAdapter = new ApplicationsAdapter(launcher, mApplications);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800120 }
121
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800122 mApplicationsLoaded = false;
123
124 if (!isLaunching) {
125 startApplicationsLoader(launcher);
The Android Open Source Projectca9475f2009-03-13 13:04:24 -0700126 return false;
127 }
128
129 return true;
130 }
131
132 private synchronized void waitForApplicationsLoader() {
133 if (mApplicationsLoader != null && mApplicationsLoader.isRunning()) {
134 android.util.Log.d("Home", " --> wait for applications loader");
135
136 mApplicationsLoader.stop();
137 // Wait for the currently running thread to finish, this can take a little
138 // time but it should be well below the timeout limit
139 try {
140 mApplicationsLoaderThread.join(APPLICATION_NOT_RESPONDING_TIMEOUT);
141 } catch (InterruptedException e) {
142 // EMpty
143 }
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800144 }
145 }
146
The Android Open Source Projectca9475f2009-03-13 13:04:24 -0700147 private synchronized void startApplicationsLoader(Launcher launcher) {
148android.util.Log.d("Home", " --> starting applications loader");
149 waitForApplicationsLoader();
150
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800151 mApplicationsLoader = new ApplicationsLoader(launcher);
The Android Open Source Projectca9475f2009-03-13 13:04:24 -0700152 mApplicationsLoaderThread = new Thread(mApplicationsLoader, "Applications Loader");
153 mApplicationsLoaderThread.start();
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800154 }
155
156 private class ApplicationsLoader implements Runnable {
157 private final WeakReference<Launcher> mLauncher;
158
159 private volatile boolean mStopped;
160 private volatile boolean mRunning;
161
162 ApplicationsLoader(Launcher launcher) {
163 mLauncher = new WeakReference<Launcher>(launcher);
164 }
165
166 void stop() {
167 mStopped = true;
168 }
169
170 boolean isRunning() {
171 return mRunning;
172 }
173
174 public void run() {
175 mRunning = true;
176
177 android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
178
179 Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
180 mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
181
182 final Launcher launcher = mLauncher.get();
183 final PackageManager manager = launcher.getPackageManager();
184 final List<ResolveInfo> apps = manager.queryIntentActivities(mainIntent, 0);
185
186 if (apps != null && !mStopped) {
187 final int count = apps.size();
188 final ApplicationsAdapter applicationList = mApplicationsAdapter;
189
The Android Open Source Projectca9475f2009-03-13 13:04:24 -0700190 ChangeNotifier action = new ChangeNotifier(applicationList, true);
The Android Open Source Project7376fae2009-03-11 12:11:58 -0700191 final HashMap<ComponentName, ApplicationInfo> appInfoCache = mAppInfoCache;
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800192
193 for (int i = 0; i < count && !mStopped; i++) {
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800194 ResolveInfo info = apps.get(i);
The Android Open Source Projectbc219c32009-03-09 11:52:14 -0700195 ComponentName componentName = new ComponentName(
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800196 info.activityInfo.applicationInfo.packageName,
The Android Open Source Projectbc219c32009-03-09 11:52:14 -0700197 info.activityInfo.name);
The Android Open Source Project7376fae2009-03-11 12:11:58 -0700198 ApplicationInfo application = appInfoCache.get(componentName);
The Android Open Source Projectbc219c32009-03-09 11:52:14 -0700199 if (application == null) {
200 application = new ApplicationInfo();
201 application.title = info.loadLabel(manager);
202 if (application.title == null) {
203 application.title = info.activityInfo.name;
204 }
205 application.setActivity(componentName,
206 Intent.FLAG_ACTIVITY_NEW_TASK |
207 Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
208 application.container = ItemInfo.NO_ID;
209 application.icon = info.activityInfo.loadIcon(manager);
210 if (DEBUG) {
211 Log.d(Launcher.LOG_TAG, "Loaded ApplicationInfo for " + componentName);
212 }
The Android Open Source Project7376fae2009-03-11 12:11:58 -0700213 appInfoCache.put(componentName, application);
The Android Open Source Projectbc219c32009-03-09 11:52:14 -0700214 }
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800215
The Android Open Source Projectca9475f2009-03-13 13:04:24 -0700216 if (action.add(application)) {
217 launcher.runOnUiThread(action);
218 action = new ChangeNotifier(applicationList, false);
219 }
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800220 }
The Android Open Source Projectca9475f2009-03-13 13:04:24 -0700221
222 launcher.runOnUiThread(action);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800223 }
224
225 if (!mStopped) {
226 mApplicationsLoaded = true;
227 }
228 mRunning = false;
229 }
230 }
231
The Android Open Source Project7376fae2009-03-11 12:11:58 -0700232 private static class ChangeNotifier implements Runnable, Comparator<ApplicationInfo> {
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800233 private final ApplicationsAdapter mApplicationList;
The Android Open Source Projectbc219c32009-03-09 11:52:14 -0700234 private final ArrayList<ApplicationInfo> mBuffer;
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800235
The Android Open Source Project7376fae2009-03-11 12:11:58 -0700236 private boolean mFirst = true;
237
The Android Open Source Projectca9475f2009-03-13 13:04:24 -0700238 ChangeNotifier(ApplicationsAdapter applicationList, boolean first) {
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800239 mApplicationList = applicationList;
The Android Open Source Projectca9475f2009-03-13 13:04:24 -0700240 mFirst = first;
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800241 mBuffer = new ArrayList<ApplicationInfo>(UI_NOTIFICATION_RATE);
242 }
243
244 public void run() {
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800245 final ApplicationsAdapter applicationList = mApplicationList;
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800246
The Android Open Source Project7376fae2009-03-11 12:11:58 -0700247 if (mFirst) {
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800248 applicationList.setNotifyOnChange(false);
The Android Open Source Project7376fae2009-03-11 12:11:58 -0700249 applicationList.clear();
250 mFirst = false;
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800251 }
252
The Android Open Source Projectca9475f2009-03-13 13:04:24 -0700253 final ArrayList<ApplicationInfo> buffer = mBuffer;
254 final int count = buffer.size();
The Android Open Source Project7376fae2009-03-11 12:11:58 -0700255
The Android Open Source Projectca9475f2009-03-13 13:04:24 -0700256 for (int i = 0; i < count; i++) {
257 applicationList.setNotifyOnChange(false);
258 applicationList.add(buffer.get(i));
The Android Open Source Project7376fae2009-03-11 12:11:58 -0700259 }
260
The Android Open Source Projectca9475f2009-03-13 13:04:24 -0700261 buffer.clear();
262
The Android Open Source Project7376fae2009-03-11 12:11:58 -0700263 applicationList.sort(this);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800264 applicationList.notifyDataSetChanged();
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800265 }
266
The Android Open Source Projectca9475f2009-03-13 13:04:24 -0700267 boolean add(ApplicationInfo application) {
268 final ArrayList<ApplicationInfo> buffer = mBuffer;
269 buffer.add(application);
270 return buffer.size() >= UI_NOTIFICATION_RATE;
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800271 }
272
The Android Open Source Project7376fae2009-03-11 12:11:58 -0700273 public final int compare(ApplicationInfo a, ApplicationInfo b) {
274 return sCollator.compare(a.title.toString(), b.title.toString());
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800275 }
276 }
277
278 boolean isDesktopLoaded() {
The Android Open Source Project7376fae2009-03-11 12:11:58 -0700279 return mDesktopItems != null && mDesktopAppWidgets != null && mDesktopItemsLoaded;
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800280 }
The Android Open Source Projectbc219c32009-03-09 11:52:14 -0700281
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800282 /**
283 * Loads all of the items on the desktop, in folders, or in the dock.
284 * These can be apps, shortcuts or widgets
285 */
286 void loadUserItems(boolean isLaunching, Launcher launcher, boolean localeChanged,
287 boolean loadApplications) {
The Android Open Source Projectca9475f2009-03-13 13:04:24 -0700288android.util.Log.d("Home", "loading user items");
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800289
290 if (isLaunching && isDesktopLoaded()) {
The Android Open Source Projectca9475f2009-03-13 13:04:24 -0700291android.util.Log.d("Home", " --> items loaded, return");
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800292 if (loadApplications) startApplicationsLoader(launcher);
293 // We have already loaded our data from the DB
294 launcher.onDesktopItemsLoaded();
295 return;
296 }
297
298 if (mDesktopItemsLoader != null && mDesktopItemsLoader.isRunning()) {
299 mDesktopItemsLoader.stop();
300 // Wait for the currently running thread to finish, this can take a little
301 // time but it should be well below the timeout limit
302 try {
The Android Open Source Projectca9475f2009-03-13 13:04:24 -0700303 mDesktopLoaderThread.join(APPLICATION_NOT_RESPONDING_TIMEOUT);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800304 } catch (InterruptedException e) {
305 // Empty
306 }
307 }
308
The Android Open Source Projectca9475f2009-03-13 13:04:24 -0700309android.util.Log.d("Home", " --> starting workspace loader");
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800310 mDesktopItemsLoaded = false;
311 mDesktopItemsLoader = new DesktopItemsLoader(launcher, localeChanged, loadApplications);
The Android Open Source Projectca9475f2009-03-13 13:04:24 -0700312 mDesktopLoaderThread = new Thread(mDesktopItemsLoader, "Desktop Items Loader");
313 mDesktopLoaderThread.start();
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800314 }
315
316 private static void updateShortcutLabels(ContentResolver resolver, PackageManager manager) {
317 final Cursor c = resolver.query(LauncherSettings.Favorites.CONTENT_URI,
318 new String[] { LauncherSettings.Favorites.ID, LauncherSettings.Favorites.TITLE,
319 LauncherSettings.Favorites.INTENT, LauncherSettings.Favorites.ITEM_TYPE },
320 null, null, null);
321
322 final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ID);
323 final int intentIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT);
324 final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
325 final int titleIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE);
326
327 // boolean changed = false;
328
329 try {
330 while (c.moveToNext()) {
331 try {
332 if (c.getInt(itemTypeIndex) !=
333 LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
334 continue;
335 }
336
337 final String intentUri = c.getString(intentIndex);
338 if (intentUri != null) {
339 final Intent shortcut = Intent.getIntent(intentUri);
340 if (Intent.ACTION_MAIN.equals(shortcut.getAction())) {
341 final ComponentName name = shortcut.getComponent();
342 if (name != null) {
343 final ActivityInfo activityInfo = manager.getActivityInfo(name, 0);
344 final String title = c.getString(titleIndex);
345 String label = getLabel(manager, activityInfo);
346
347 if (title == null || !title.equals(label)) {
348 final ContentValues values = new ContentValues();
349 values.put(LauncherSettings.Favorites.TITLE, label);
350
351 resolver.update(LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION,
352 values, "_id=?",
353 new String[] { String.valueOf(c.getLong(idIndex)) });
354
355 // changed = true;
356 }
357 }
358 }
359 }
360 } catch (URISyntaxException e) {
361 // Ignore
362 } catch (PackageManager.NameNotFoundException e) {
363 // Ignore
364 }
365 }
366 } finally {
367 c.close();
368 }
369
370 // if (changed) resolver.notifyChange(Settings.Favorites.CONTENT_URI, null);
371 }
372
373 private static String getLabel(PackageManager manager, ActivityInfo activityInfo) {
374 String label = activityInfo.loadLabel(manager).toString();
375 if (label == null) {
376 label = manager.getApplicationLabel(activityInfo.applicationInfo).toString();
377 if (label == null) {
378 label = activityInfo.name;
379 }
380 }
381 return label;
382 }
383
384 private class DesktopItemsLoader implements Runnable {
385 private volatile boolean mStopped;
386 private volatile boolean mRunning;
387
388 private final WeakReference<Launcher> mLauncher;
389 private final boolean mLocaleChanged;
390 private final boolean mLoadApplications;
391
392 DesktopItemsLoader(Launcher launcher, boolean localeChanged, boolean loadApplications) {
393 mLoadApplications = loadApplications;
394 mLauncher = new WeakReference<Launcher>(launcher);
395 mLocaleChanged = localeChanged;
396 }
397
398 void stop() {
399 mStopped = true;
400 }
401
402 boolean isRunning() {
403 return mRunning;
404 }
405
406 public void run() {
407 mRunning = true;
408
409 final Launcher launcher = mLauncher.get();
410 final ContentResolver contentResolver = launcher.getContentResolver();
411 final PackageManager manager = launcher.getPackageManager();
412
413 if (mLocaleChanged) {
414 updateShortcutLabels(contentResolver, manager);
415 }
416
417 mDesktopItems = new ArrayList<ItemInfo>();
The Android Open Source Project7376fae2009-03-11 12:11:58 -0700418 mDesktopAppWidgets = new ArrayList<LauncherAppWidgetInfo>();
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800419 mFolders = new HashMap<Long, FolderInfo>();
420
421 final ArrayList<ItemInfo> desktopItems = mDesktopItems;
The Android Open Source Project7376fae2009-03-11 12:11:58 -0700422 final ArrayList<LauncherAppWidgetInfo> desktopAppWidgets = mDesktopAppWidgets;
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800423
424 final Cursor c = contentResolver.query(
425 LauncherSettings.Favorites.CONTENT_URI, null, null, null, null);
426
427 try {
428 final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ID);
429 final int intentIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT);
430 final int titleIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE);
431 final int iconTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_TYPE);
432 final int iconIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON);
433 final int iconPackageIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_PACKAGE);
434 final int iconResourceIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_RESOURCE);
435 final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);
436 final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
The Android Open Source Project7376fae2009-03-11 12:11:58 -0700437 final int appWidgetIdIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.APPWIDGET_ID);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800438 final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
439 final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);
440 final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);
441 final int spanXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANX);
442 final int spanYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANY);
443 final int uriIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.URI);
444 final int displayModeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.DISPLAY_MODE);
445
446 ApplicationInfo info;
447 String intentDescription;
448 Widget widgetInfo;
The Android Open Source Project7376fae2009-03-11 12:11:58 -0700449 LauncherAppWidgetInfo appWidgetInfo;
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800450 int container;
451 long id;
452 Intent intent;
453
454 final HashMap<Long, FolderInfo> folders = mFolders;
455
456 while (!mStopped && c.moveToNext()) {
457 try {
458 int itemType = c.getInt(itemTypeIndex);
459
460 switch (itemType) {
461 case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
462 case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
463 intentDescription = c.getString(intentIndex);
464 try {
465 intent = Intent.getIntent(intentDescription);
466 } catch (java.net.URISyntaxException e) {
467 continue;
468 }
469
470 if (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
471 info = getApplicationInfo(manager, intent);
472 } else {
473 info = getApplicationInfoShortcut(c, launcher, iconTypeIndex,
474 iconPackageIndex, iconResourceIndex, iconIndex);
475 }
476
477 if (info == null) {
478 info = new ApplicationInfo();
479 info.icon = manager.getDefaultActivityIcon();
480 }
481
482 if (info != null) {
483 info.title = c.getString(titleIndex);
484 info.intent = intent;
485
486 info.id = c.getLong(idIndex);
487 container = c.getInt(containerIndex);
488 info.container = container;
489 info.screen = c.getInt(screenIndex);
490 info.cellX = c.getInt(cellXIndex);
491 info.cellY = c.getInt(cellYIndex);
492
493 switch (container) {
494 case LauncherSettings.Favorites.CONTAINER_DESKTOP:
495 desktopItems.add(info);
496 break;
497 default:
498 // Item is in a user folder
499 UserFolderInfo folderInfo =
500 findOrMakeUserFolder(folders, container);
501 folderInfo.add(info);
502 break;
503 }
504 }
505 break;
506 case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
507
508 id = c.getLong(idIndex);
509 UserFolderInfo folderInfo = findOrMakeUserFolder(folders, id);
510
511 folderInfo.title = c.getString(titleIndex);
512
513 folderInfo.id = id;
514 container = c.getInt(containerIndex);
515 folderInfo.container = container;
516 folderInfo.screen = c.getInt(screenIndex);
517 folderInfo.cellX = c.getInt(cellXIndex);
518 folderInfo.cellY = c.getInt(cellYIndex);
519
520 switch (container) {
521 case LauncherSettings.Favorites.CONTAINER_DESKTOP:
522 desktopItems.add(folderInfo);
523 break;
524 }
525 break;
526 case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
527
528 id = c.getLong(idIndex);
529 LiveFolderInfo liveFolderInfo = findOrMakeLiveFolder(folders, id);
530
531 intentDescription = c.getString(intentIndex);
532 intent = null;
533 if (intentDescription != null) {
534 try {
535 intent = Intent.getIntent(intentDescription);
536 } catch (java.net.URISyntaxException e) {
537 // Ignore, a live folder might not have a base intent
538 }
539 }
540
541 liveFolderInfo.title = c.getString(titleIndex);
542 liveFolderInfo.id = id;
543 container = c.getInt(containerIndex);
544 liveFolderInfo.container = container;
545 liveFolderInfo.screen = c.getInt(screenIndex);
546 liveFolderInfo.cellX = c.getInt(cellXIndex);
547 liveFolderInfo.cellY = c.getInt(cellYIndex);
548 liveFolderInfo.uri = Uri.parse(c.getString(uriIndex));
549 liveFolderInfo.baseIntent = intent;
550 liveFolderInfo.displayMode = c.getInt(displayModeIndex);
551
552 loadLiveFolderIcon(launcher, c, iconTypeIndex, iconPackageIndex,
553 iconResourceIndex, liveFolderInfo);
554
555 switch (container) {
556 case LauncherSettings.Favorites.CONTAINER_DESKTOP:
557 desktopItems.add(liveFolderInfo);
558 break;
559 }
560 break;
561 case LauncherSettings.Favorites.ITEM_TYPE_WIDGET_SEARCH:
562 widgetInfo = Widget.makeSearch();
563
564 container = c.getInt(containerIndex);
565 if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
566 Log.e(Launcher.LOG_TAG, "Widget found where container "
567 + "!= CONTAINER_DESKTOP ignoring!");
568 continue;
569 }
The Android Open Source Projectbc219c32009-03-09 11:52:14 -0700570
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800571 widgetInfo.id = c.getLong(idIndex);
572 widgetInfo.screen = c.getInt(screenIndex);
573 widgetInfo.container = container;
574 widgetInfo.cellX = c.getInt(cellXIndex);
575 widgetInfo.cellY = c.getInt(cellYIndex);
576
577 desktopItems.add(widgetInfo);
578 break;
The Android Open Source Project7376fae2009-03-11 12:11:58 -0700579 case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
580 // Read all Launcher-specific widget details
581 int appWidgetId = c.getInt(appWidgetIdIndex);
582 appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId);
583 appWidgetInfo.id = c.getLong(idIndex);
584 appWidgetInfo.screen = c.getInt(screenIndex);
585 appWidgetInfo.cellX = c.getInt(cellXIndex);
586 appWidgetInfo.cellY = c.getInt(cellYIndex);
587 appWidgetInfo.spanX = c.getInt(spanXIndex);
588 appWidgetInfo.spanY = c.getInt(spanYIndex);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800589
590 container = c.getInt(containerIndex);
591 if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
The Android Open Source Project7376fae2009-03-11 12:11:58 -0700592 Log.e(Launcher.LOG_TAG, "Widget found where container "
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800593 + "!= CONTAINER_DESKTOP -- ignoring!");
594 continue;
595 }
The Android Open Source Project7376fae2009-03-11 12:11:58 -0700596 appWidgetInfo.container = c.getInt(containerIndex);
The Android Open Source Projectbc219c32009-03-09 11:52:14 -0700597
The Android Open Source Project7376fae2009-03-11 12:11:58 -0700598 desktopAppWidgets.add(appWidgetInfo);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800599 break;
600 }
601 } catch (Exception e) {
602 Log.w(Launcher.LOG_TAG, "Desktop items loading interrupted:", e);
603 }
604 }
605 } finally {
606 c.close();
607 }
608
609 if (!mStopped) {
610 launcher.runOnUiThread(new Runnable() {
611 public void run() {
612 launcher.onDesktopItemsLoaded();
613 }
614 });
615 if (mLoadApplications) startApplicationsLoader(launcher);
616 }
617
618 if (!mStopped) {
619 mDesktopItemsLoaded = true;
620 }
621 mRunning = false;
622 }
623 }
624
625 private static void loadLiveFolderIcon(Launcher launcher, Cursor c, int iconTypeIndex,
626 int iconPackageIndex, int iconResourceIndex, LiveFolderInfo liveFolderInfo) {
627
628 int iconType = c.getInt(iconTypeIndex);
629 switch (iconType) {
630 case LauncherSettings.Favorites.ICON_TYPE_RESOURCE:
631 String packageName = c.getString(iconPackageIndex);
632 String resourceName = c.getString(iconResourceIndex);
633 PackageManager packageManager = launcher.getPackageManager();
634 try {
635 Resources resources = packageManager.getResourcesForApplication(packageName);
636 final int id = resources.getIdentifier(resourceName, null, null);
637 liveFolderInfo.icon = resources.getDrawable(id);
638 } catch (Exception e) {
639 liveFolderInfo.icon =
640 launcher.getResources().getDrawable(R.drawable.ic_launcher_folder);
641 }
642 liveFolderInfo.iconResource = new Intent.ShortcutIconResource();
643 liveFolderInfo.iconResource.packageName = packageName;
644 liveFolderInfo.iconResource.resourceName = resourceName;
645 break;
646 default:
647 liveFolderInfo.icon =
The Android Open Source Projectbc219c32009-03-09 11:52:14 -0700648 launcher.getResources().getDrawable(R.drawable.ic_launcher_folder);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800649 }
650 }
651
652 /**
653 * Finds the user folder defined by the specified id.
654 *
655 * @param id The id of the folder to look for.
The Android Open Source Projectbc219c32009-03-09 11:52:14 -0700656 *
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800657 * @return A UserFolderInfo if the folder exists or null otherwise.
658 */
659 FolderInfo findFolderById(long id) {
660 return mFolders.get(id);
661 }
662
663 void addFolder(FolderInfo info) {
664 mFolders.put(info.id, info);
665 }
666
667 /**
668 * Return an existing UserFolderInfo object if we have encountered this ID previously, or make a
669 * new one.
670 */
671 private UserFolderInfo findOrMakeUserFolder(HashMap<Long, FolderInfo> folders, long id) {
672 // See if a placeholder was created for us already
673 FolderInfo folderInfo = folders.get(id);
674 if (folderInfo == null || !(folderInfo instanceof UserFolderInfo)) {
675 // No placeholder -- create a new instance
676 folderInfo = new UserFolderInfo();
677 folders.put(id, folderInfo);
678 }
679 return (UserFolderInfo) folderInfo;
680 }
681
682 /**
683 * Return an existing UserFolderInfo object if we have encountered this ID previously, or make a
684 * new one.
685 */
686 private LiveFolderInfo findOrMakeLiveFolder(HashMap<Long, FolderInfo> folders, long id) {
687 // See if a placeholder was created for us already
688 FolderInfo folderInfo = folders.get(id);
689 if (folderInfo == null || !(folderInfo instanceof LiveFolderInfo)) {
690 // No placeholder -- create a new instance
691 folderInfo = new LiveFolderInfo();
692 folders.put(id, folderInfo);
693 }
694 return (LiveFolderInfo) folderInfo;
695 }
696
697 /**
698 * Remove the callback for the cached drawables or we leak the previous
699 * Home screen on orientation change.
700 */
701 void unbind() {
702 mApplicationsAdapter = null;
703 unbindAppDrawables(mApplications);
704 unbindDrawables(mDesktopItems);
The Android Open Source Project7376fae2009-03-11 12:11:58 -0700705 unbindAppWidgetHostViews(mDesktopAppWidgets);
The Android Open Source Projectbc219c32009-03-09 11:52:14 -0700706 unbindCachedIconDrawables();
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800707 }
The Android Open Source Projectbc219c32009-03-09 11:52:14 -0700708
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800709 /**
710 * Remove the callback for the cached drawables or we leak the previous
711 * Home screen on orientation change.
712 */
713 private void unbindDrawables(ArrayList<ItemInfo> desktopItems) {
714 if (desktopItems != null) {
715 final int count = desktopItems.size();
716 for (int i = 0; i < count; i++) {
717 ItemInfo item = desktopItems.get(i);
718 switch (item.itemType) {
719 case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
720 case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
721 ((ApplicationInfo)item).icon.setCallback(null);
722 break;
723 }
724 }
725 }
726 }
The Android Open Source Projectbc219c32009-03-09 11:52:14 -0700727
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800728 /**
729 * Remove the callback for the cached drawables or we leak the previous
730 * Home screen on orientation change.
731 */
732 private void unbindAppDrawables(ArrayList<ApplicationInfo> applications) {
733 if (applications != null) {
734 final int count = applications.size();
735 for (int i = 0; i < count; i++) {
736 applications.get(i).icon.setCallback(null);
737 }
738 }
739 }
740
741 /**
The Android Open Source Project7376fae2009-03-11 12:11:58 -0700742 * Remove any {@link LauncherAppWidgetHostView} references in our widgets.
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800743 */
The Android Open Source Project7376fae2009-03-11 12:11:58 -0700744 private void unbindAppWidgetHostViews(ArrayList<LauncherAppWidgetInfo> appWidgets) {
745 if (appWidgets != null) {
746 final int count = appWidgets.size();
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800747 for (int i = 0; i < count; i++) {
The Android Open Source Project7376fae2009-03-11 12:11:58 -0700748 LauncherAppWidgetInfo launcherInfo = appWidgets.get(i);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800749 launcherInfo.hostView = null;
750 }
751 }
752 }
753
754 /**
The Android Open Source Projectbc219c32009-03-09 11:52:14 -0700755 * Remove the callback for the cached drawables or we leak the previous
756 * Home screen on orientation change.
757 */
758 private void unbindCachedIconDrawables() {
759 for (ApplicationInfo appInfo : mAppInfoCache.values()) {
760 appInfo.icon.setCallback(null);
761 }
762 }
763
764 /**
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800765 * @return The current list of applications
766 */
The Android Open Source Projectca9475f2009-03-13 13:04:24 -0700767 ApplicationsAdapter getApplicationsAdapter() {
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800768 return mApplicationsAdapter;
769 }
770
771 /**
772 * @return The current list of desktop items
773 */
The Android Open Source Projectca9475f2009-03-13 13:04:24 -0700774 ArrayList<ItemInfo> getDesktopItems() {
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800775 return mDesktopItems;
776 }
777
778 /**
779 * @return The current list of desktop items
780 */
The Android Open Source Projectca9475f2009-03-13 13:04:24 -0700781 ArrayList<LauncherAppWidgetInfo> getDesktopAppWidgets() {
The Android Open Source Project7376fae2009-03-11 12:11:58 -0700782 return mDesktopAppWidgets;
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800783 }
784
785 /**
786 * Add an item to the desktop
787 * @param info
788 */
The Android Open Source Projectca9475f2009-03-13 13:04:24 -0700789 void addDesktopItem(ItemInfo info) {
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800790 // TODO: write to DB; also check that folder has been added to folders list
791 mDesktopItems.add(info);
792 }
793
794 /**
795 * Remove an item from the desktop
796 * @param info
797 */
The Android Open Source Projectca9475f2009-03-13 13:04:24 -0700798 void removeDesktopItem(ItemInfo info) {
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800799 // TODO: write to DB; figure out if we should remove folder from folders list
800 mDesktopItems.remove(info);
801 }
802
803 /**
The Android Open Source Project7376fae2009-03-11 12:11:58 -0700804 * Add a widget to the desktop
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800805 */
The Android Open Source Projectca9475f2009-03-13 13:04:24 -0700806 void addDesktopAppWidget(LauncherAppWidgetInfo info) {
The Android Open Source Project7376fae2009-03-11 12:11:58 -0700807 mDesktopAppWidgets.add(info);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800808 }
809
810 /**
The Android Open Source Project7376fae2009-03-11 12:11:58 -0700811 * Remove a widget from the desktop
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800812 */
The Android Open Source Projectca9475f2009-03-13 13:04:24 -0700813 void removeDesktopAppWidget(LauncherAppWidgetInfo info) {
The Android Open Source Project7376fae2009-03-11 12:11:58 -0700814 mDesktopAppWidgets.remove(info);
The Android Open Source Project31dd5032009-03-03 19:32:27 -0800815 }
816
817 /**
818 * Make an ApplicationInfo object for an application
819 */
820 private static ApplicationInfo getApplicationInfo(PackageManager manager, Intent intent) {
821 final ResolveInfo resolveInfo = manager.resolveActivity(intent, 0);
822
823 if (resolveInfo == null) {
824 return null;
825 }
826
827 final ApplicationInfo info = new ApplicationInfo();
828 final ActivityInfo activityInfo = resolveInfo.activityInfo;
829 info.icon = activityInfo.loadIcon(manager);
830 if (info.title == null || info.title.length() == 0) {
831 info.title = activityInfo.loadLabel(manager);
832 }
833 if (info.title == null) {
834 info.title = "";
835 }
836 info.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
837 return info;
838 }
839
840 /**
841 * Make an ApplicationInfo object for a sortcut
842 */
843 private ApplicationInfo getApplicationInfoShortcut(Cursor c, Launcher launcher,
844 int iconTypeIndex, int iconPackageIndex, int iconResourceIndex, int iconIndex) {
845
846 final ApplicationInfo info = new ApplicationInfo();
847 info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
848
849 int iconType = c.getInt(iconTypeIndex);
850 switch (iconType) {
851 case LauncherSettings.Favorites.ICON_TYPE_RESOURCE:
852 String packageName = c.getString(iconPackageIndex);
853 String resourceName = c.getString(iconResourceIndex);
854 PackageManager packageManager = launcher.getPackageManager();
855 try {
856 Resources resources = packageManager.getResourcesForApplication(packageName);
857 final int id = resources.getIdentifier(resourceName, null, null);
858 info.icon = resources.getDrawable(id);
859 } catch (Exception e) {
860 info.icon = packageManager.getDefaultActivityIcon();
861 }
862 info.iconResource = new Intent.ShortcutIconResource();
863 info.iconResource.packageName = packageName;
864 info.iconResource.resourceName = resourceName;
865 info.customIcon = false;
866 break;
867 case LauncherSettings.Favorites.ICON_TYPE_BITMAP:
868 byte[] data = c.getBlob(iconIndex);
869 Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
870 info.icon = new FastBitmapDrawable(
871 Utilities.createBitmapThumbnail(bitmap, launcher));
872 info.filtered = true;
873 info.customIcon = true;
874 break;
875 default:
876 info.icon = launcher.getPackageManager().getDefaultActivityIcon();
877 info.customIcon = false;
878 break;
879 }
880 return info;
881 }
882
883 /**
884 * Remove an item from the in-memory represention of a user folder. Does not change the DB.
885 */
886 void removeUserFolderItem(UserFolderInfo folder, ItemInfo info) {
887 //noinspection SuspiciousMethodCalls
888 folder.contents.remove(info);
889 }
890
891 /**
892 * Removes a UserFolder from the in-memory list of folders. Does not change the DB.
893 * @param userFolderInfo
894 */
895 void removeUserFolder(UserFolderInfo userFolderInfo) {
896 mFolders.remove(userFolderInfo.id);
897 }
898
899 /**
900 * Adds an item to the DB if it was not created previously, or move it to a new
901 * <container, screen, cellX, cellY>
902 */
903 static void addOrMoveItemInDatabase(Context context, ItemInfo item, long container,
904 int screen, int cellX, int cellY) {
905 if (item.container == ItemInfo.NO_ID) {
906 // From all apps
907 addItemToDatabase(context, item, container, screen, cellX, cellY, false);
908 } else {
909 // From somewhere else
910 moveItemInDatabase(context, item, container, screen, cellX, cellY);
911 }
912 }
913
914 /**
915 * Move an item in the DB to a new <container, screen, cellX, cellY>
916 */
917 static void moveItemInDatabase(Context context, ItemInfo item, long container, int screen,
918 int cellX, int cellY) {
919 item.container = container;
920 item.screen = screen;
921 item.cellX = cellX;
922 item.cellY = cellY;
923
924 final ContentValues values = new ContentValues();
925 final ContentResolver cr = context.getContentResolver();
926
927 values.put(LauncherSettings.Favorites.CONTAINER, item.container);
928 values.put(LauncherSettings.Favorites.CELLX, item.cellX);
929 values.put(LauncherSettings.Favorites.CELLY, item.cellY);
930 values.put(LauncherSettings.Favorites.SCREEN, item.screen);
931
932 cr.update(LauncherSettings.Favorites.getContentUri(item.id, false), values, null, null);
933 }
934
935 /**
936 * Returns true if the shortcuts already exists in the database.
937 * we identify a shortcut by its title and intent.
938 */
939 static boolean shortcutExists(Context context, String title, Intent intent) {
940 final ContentResolver cr = context.getContentResolver();
941 Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI,
942 new String[] { "title", "intent" }, "title=? and intent=?",
943 new String[] { title, intent.toURI() }, null);
944 boolean result = false;
945 try {
946 result = c.moveToFirst();
947 } finally {
948 c.close();
949 }
950 return result;
951 }
952
953 FolderInfo getFolderById(Context context, long id) {
954 final ContentResolver cr = context.getContentResolver();
955 Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, null,
956 "_id=? and itemType=? or itemType=?",
957 new String[] { String.valueOf(id),
958 String.valueOf(LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER),
959 String.valueOf(LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER) }, null);
960
961 try {
962 if (c.moveToFirst()) {
963 final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
964 final int titleIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE);
965 final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);
966 final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
967 final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);
968 final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);
969
970 FolderInfo folderInfo = null;
971 switch (c.getInt(itemTypeIndex)) {
972 case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER:
973 folderInfo = findOrMakeUserFolder(mFolders, id);
974 break;
975 case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER:
976 folderInfo = findOrMakeLiveFolder(mFolders, id);
977 break;
978 }
979
980 folderInfo.title = c.getString(titleIndex);
981 folderInfo.id = id;
982 folderInfo.container = c.getInt(containerIndex);
983 folderInfo.screen = c.getInt(screenIndex);
984 folderInfo.cellX = c.getInt(cellXIndex);
985 folderInfo.cellY = c.getInt(cellYIndex);
986
987 return folderInfo;
988 }
989 } finally {
990 c.close();
991 }
992
993 return null;
994 }
995
996 /**
997 * Add an item to the database in a specified container. Sets the container, screen, cellX and
998 * cellY fields of the item. Also assigns an ID to the item.
999 */
1000 static void addItemToDatabase(Context context, ItemInfo item, long container,
1001 int screen, int cellX, int cellY, boolean notify) {
1002 item.container = container;
1003 item.screen = screen;
1004 item.cellX = cellX;
1005 item.cellY = cellY;
1006
1007 final ContentValues values = new ContentValues();
1008 final ContentResolver cr = context.getContentResolver();
1009
1010 item.onAddToDatabase(values);
1011
1012 Uri result = cr.insert(notify ? LauncherSettings.Favorites.CONTENT_URI :
1013 LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION, values);
1014
1015 if (result != null) {
1016 item.id = Integer.parseInt(result.getPathSegments().get(1));
1017 }
1018 }
1019
1020 /**
1021 * Update an item to the database in a specified container.
1022 */
1023 static void updateItemInDatabase(Context context, ItemInfo item) {
1024 final ContentValues values = new ContentValues();
1025 final ContentResolver cr = context.getContentResolver();
1026
1027 item.onAddToDatabase(values);
1028
1029 cr.update(LauncherSettings.Favorites.getContentUri(item.id, false), values, null, null);
1030 }
1031
1032 /**
1033 * Removes the specified item from the database
1034 * @param context
1035 * @param item
1036 */
1037 static void deleteItemFromDatabase(Context context, ItemInfo item) {
1038 final ContentResolver cr = context.getContentResolver();
1039
1040 cr.delete(LauncherSettings.Favorites.getContentUri(item.id, false), null, null);
1041 }
1042
1043
1044 /**
1045 * Remove the contents of the specified folder from the database
1046 */
1047 static void deleteUserFolderContentsFromDatabase(Context context, UserFolderInfo info) {
1048 final ContentResolver cr = context.getContentResolver();
1049
1050 cr.delete(LauncherSettings.Favorites.getContentUri(info.id, false), null, null);
1051 cr.delete(LauncherSettings.Favorites.CONTENT_URI,
1052 LauncherSettings.Favorites.CONTAINER + "=" + info.id, null);
1053 }
1054}