summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMichael Jurka <mikejurka@google.com>2011-04-28 14:59:33 -0700
committerMichael Jurka <mikejurka@google.com>2011-07-08 14:06:14 -0700
commita8c760d395e1d2a78522427738302fbca3a72453 (patch)
tree03ab4d4bfd3802c232e2d5e57c663530ae684ac1 /src
parentf62e8fdee31cbd80c84d41ca5a9756cc7defe1a9 (diff)
downloadandroid_packages_apps_Trebuchet-a8c760d395e1d2a78522427738302fbca3a72453.tar.gz
android_packages_apps_Trebuchet-a8c760d395e1d2a78522427738302fbca3a72453.tar.bz2
android_packages_apps_Trebuchet-a8c760d395e1d2a78522427738302fbca3a72453.zip
Improving LauncherModel performance
- no longer reloading DB on each configuration change - adding/updating items in DB on background thread Change-Id: Ie140f31608df84b0ca2d45eb7a210a8a3b36b52f
Diffstat (limited to 'src')
-rw-r--r--src/com/android/launcher2/LauncherApplication.java11
-rw-r--r--src/com/android/launcher2/LauncherModel.java193
-rw-r--r--src/com/android/launcher2/LauncherProvider.java73
3 files changed, 209 insertions, 68 deletions
diff --git a/src/com/android/launcher2/LauncherApplication.java b/src/com/android/launcher2/LauncherApplication.java
index 68b164436..db3a4cbe4 100644
--- a/src/com/android/launcher2/LauncherApplication.java
+++ b/src/com/android/launcher2/LauncherApplication.java
@@ -24,11 +24,14 @@ import android.content.res.Configuration;
import android.database.ContentObserver;
import android.os.Handler;
+import java.lang.ref.WeakReference;
+
public class LauncherApplication extends Application {
public LauncherModel mModel;
public IconCache mIconCache;
private static boolean sIsScreenLarge;
private static float sScreenDensity;
+ WeakReference<LauncherProvider> mLauncherProvider;
@Override
public void onCreate() {
@@ -97,6 +100,14 @@ public class LauncherApplication extends Application {
return mModel;
}
+ void setLauncherProvider(LauncherProvider provider) {
+ mLauncherProvider = new WeakReference<LauncherProvider>(provider);
+ }
+
+ LauncherProvider getLauncherProvider() {
+ return mLauncherProvider.get();
+ }
+
public static boolean isScreenLarge() {
return sIsScreenLarge;
}
diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java
index e8ae9d9e3..64b38c0e3 100644
--- a/src/com/android/launcher2/LauncherModel.java
+++ b/src/com/android/launcher2/LauncherModel.java
@@ -88,9 +88,27 @@ public class LauncherModel extends BroadcastReceiver {
private WeakReference<Callbacks> mCallbacks;
- private AllAppsList mAllAppsList; // only access in worker thread
- private IconCache mIconCache;
+ // < only access in worker thread >
+ private AllAppsList mAllAppsList;
+
+ // sItemsIdMap maps *all* the ItemInfos (shortcuts, folders, and widgets) created by
+ // LauncherModel to their ids
+ static final HashMap<Long, ItemInfo> sItemsIdMap = new HashMap<Long, ItemInfo>();
+
+ // sItems is passed to bindItems, which expects a list of all folders and shortcuts created by
+ // LauncherModel that are directly on the home screen (however, no widgets or shortcuts
+ // within folders).
+ static final ArrayList<ItemInfo> sItems = new ArrayList<ItemInfo>();
+ // sAppWidgets is all LauncherAppWidgetInfo created by LauncherModel. Passed to bindAppWidget()
+ static final ArrayList<LauncherAppWidgetInfo> sAppWidgets =
+ new ArrayList<LauncherAppWidgetInfo>();
+
+ // sFolders is all FolderInfos created by LauncherModel. Passed to bindFolders()
+ static final HashMap<Long, FolderInfo> sFolders = new HashMap<Long, FolderInfo>();
+ // </ only access in worker thread >
+
+ private IconCache mIconCache;
private Bitmap mDefaultIcon;
private static int mCellCountX;
@@ -148,9 +166,8 @@ public class LauncherModel extends BroadcastReceiver {
/**
* Move an item in the DB to a new <container, screen, cellX, cellY>
*/
- static void moveItemInDatabase(Context context, ItemInfo item, long container, int screen,
- int cellX, int cellY) {
-
+ static void moveItemInDatabase(Context context, final ItemInfo item, final long container,
+ final int screen, final int cellX, final int cellY) {
item.container = container;
item.screen = screen;
item.cellX = cellX;
@@ -168,6 +185,24 @@ public class LauncherModel extends BroadcastReceiver {
sWorker.post(new Runnable() {
public void run() {
cr.update(uri, values, null, null);
+ ItemInfo modelItem = sItemsIdMap.get(item.id);
+ if (item != modelItem) {
+ // the modelItem needs to match up perfectly with item if our model is to be
+ // consistent with the database-- for now, just require modelItem == item
+ throw new RuntimeException("Error: ItemInfo passed to moveItemInDatabase " +
+ "doesn't match original");
+ }
+
+ // Items are added/removed from the corresponding FolderInfo elsewhere, such
+ // as in Workspace.onDrop. Here, we just add/remove them from the list of items
+ // that are on the desktop, as appropriate
+ if (modelItem.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+ if (!sItems.contains(modelItem)) {
+ sItems.add(modelItem);
+ }
+ } else {
+ sItems.remove(modelItem);
+ }
}
});
}
@@ -175,8 +210,8 @@ public class LauncherModel extends BroadcastReceiver {
/**
* Resize an item in the DB to a new <spanX, spanY, cellX, cellY>
*/
- static void resizeItemInDatabase(Context context, ItemInfo item, int cellX, int cellY,
- int spanX, int spanY) {
+ static void resizeItemInDatabase(Context context, final ItemInfo item, final int cellX,
+ final int cellY, final int spanX, final int spanY) {
item.spanX = spanX;
item.spanY = spanY;
item.cellX = cellX;
@@ -195,6 +230,13 @@ public class LauncherModel extends BroadcastReceiver {
sWorker.post(new Runnable() {
public void run() {
cr.update(uri, values, null, null);
+ ItemInfo modelItem = sItemsIdMap.get(item.id);
+ if (item != modelItem) {
+ // the modelItem needs to match up perfectly with item if our model is to be
+ // consistent with the database-- for now, just require modelItem == item
+ throw new RuntimeException("Error: ItemInfo passed to moveItemInDatabase " +
+ "doesn't match original");
+ }
}
});
}
@@ -316,14 +358,37 @@ public class LauncherModel extends BroadcastReceiver {
final ContentResolver cr = context.getContentResolver();
item.onAddToDatabase(values);
+ Launcher l = (Launcher) context;
+ LauncherApplication app = (LauncherApplication) l.getApplication();
+ item.id = app.getLauncherProvider().generateNewId();
+ values.put(LauncherSettings.Favorites._ID, item.id);
item.updateValuesWithCoordinates(values, cellX, cellY);
- Uri result = cr.insert(notify ? LauncherSettings.Favorites.CONTENT_URI :
- LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION, values);
+ sWorker.post(new Runnable() {
+ public void run() {
+ cr.insert(notify ? LauncherSettings.Favorites.CONTENT_URI :
+ LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION, values);
- if (result != null) {
- item.id = Integer.parseInt(result.getPathSegments().get(1));
- }
+ sItemsIdMap.put(item.id, item);
+ switch (item.itemType) {
+ case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
+ sFolders.put(item.id, (FolderInfo) item);
+ if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+ sItems.add(item);
+ }
+ break;
+ case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
+ case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
+ if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+ sItems.add(item);
+ }
+ break;
+ case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
+ sAppWidgets.add((LauncherAppWidgetInfo) item);
+ break;
+ }
+ }
+ });
}
/**
@@ -355,14 +420,26 @@ public class LauncherModel extends BroadcastReceiver {
/**
* Update an item to the database in a specified container.
*/
- static void updateItemInDatabase(Context context, ItemInfo item) {
+ static void updateItemInDatabase(Context context, final ItemInfo item) {
final ContentValues values = new ContentValues();
final ContentResolver cr = context.getContentResolver();
item.onAddToDatabase(values);
item.updateValuesWithCoordinates(values, item.cellX, item.cellY);
- cr.update(LauncherSettings.Favorites.getContentUri(item.id, false), values, null, null);
+ sWorker.post(new Runnable() {
+ public void run() {
+ cr.update(LauncherSettings.Favorites.getContentUri(item.id, false),
+ values, null, null);
+ final ItemInfo modelItem = sItemsIdMap.get(item.id);
+ if (item != modelItem) {
+ // the modelItem needs to match up perfectly with item if our model is to be
+ // consistent with the database-- for now, just require modelItem == item
+ throw new RuntimeException("Error: ItemInfo passed to moveItemInDatabase " +
+ "doesn't match original");
+ }
+ }
+ });
}
/**
@@ -370,43 +447,50 @@ public class LauncherModel extends BroadcastReceiver {
* @param context
* @param item
*/
- static void deleteItemFromDatabase(Context context, ItemInfo item) {
+ static void deleteItemFromDatabase(Context context, final ItemInfo item) {
final ContentResolver cr = context.getContentResolver();
final Uri uriToDelete = LauncherSettings.Favorites.getContentUri(item.id, false);
sWorker.post(new Runnable() {
public void run() {
cr.delete(uriToDelete, null, null);
+ switch (item.itemType) {
+ case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
+ sFolders.remove(item.id);
+ sItems.remove(item);
+ break;
+ case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
+ case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
+ sItems.remove(item);
+ break;
+ case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
+ sAppWidgets.remove((LauncherAppWidgetInfo) item);
+ break;
+ }
+ sItemsIdMap.remove(item.id);
}
});
}
- static void deleteFolderContentsFromDatabase(Context context, final FolderInfo info) {
- deleteFolderContentsFromDatabase(context, info, false);
- }
-
/**
* Remove the contents of the specified folder from the database
*/
- static void deleteFolderContentsFromDatabase(Context context, final FolderInfo info,
- boolean post) {
- // TODO: this post flag is temporary to fix an ordering of commands issue. In future,
- // all db operations will be moved to the worker thread, so this can be discarded at
- // that time.
+ static void deleteFolderContentsFromDatabase(Context context, final FolderInfo info) {
final ContentResolver cr = context.getContentResolver();
- if (!post) {
- cr.delete(LauncherSettings.Favorites.getContentUri(info.id, false), null, null);
- cr.delete(LauncherSettings.Favorites.CONTENT_URI,
- LauncherSettings.Favorites.CONTAINER + "=" + info.id, null);
- } else {
- sWorker.post(new Runnable() {
+ sWorker.post(new Runnable() {
public void run() {
cr.delete(LauncherSettings.Favorites.getContentUri(info.id, false), null, null);
+ sItemsIdMap.remove(info.id);
+ sFolders.remove(info.id);
+ sItems.remove(info);
+
cr.delete(LauncherSettings.Favorites.CONTENT_URI,
LauncherSettings.Favorites.CONTAINER + "=" + info.id, null);
+ for (ItemInfo childInfo : info.contents) {
+ sItemsIdMap.remove(childInfo.id);
+ }
}
});
- }
}
/**
@@ -547,10 +631,6 @@ public class LauncherModel extends BroadcastReceiver {
private boolean mStopped;
private boolean mLoadAndBindStepFinished;
- final ArrayList<ItemInfo> mItems = new ArrayList<ItemInfo>();
- final ArrayList<LauncherAppWidgetInfo> mAppWidgets = new ArrayList<LauncherAppWidgetInfo>();
- final HashMap<Long, FolderInfo> mFolders = new HashMap<Long, FolderInfo>();
-
LoaderTask(Context context, boolean isLaunching) {
mContext = context;
mIsLaunching = isLaunching;
@@ -562,14 +642,10 @@ public class LauncherModel extends BroadcastReceiver {
private void loadAndBindWorkspace() {
// Load the workspace
-
- // For now, just always reload the workspace. It's ~100 ms vs. the
- // binding which takes many hundreds of ms.
- // We can reconsider.
if (DEBUG_LOADERS) {
Log.d(TAG, "loadAndBindWorkspace mWorkspaceLoaded=" + mWorkspaceLoaded);
}
- if (true || !mWorkspaceLoaded) {
+ if (!mWorkspaceLoaded) {
loadWorkspace();
if (mStopped) {
return;
@@ -743,9 +819,10 @@ public class LauncherModel extends BroadcastReceiver {
final AppWidgetManager widgets = AppWidgetManager.getInstance(context);
final boolean isSafeMode = manager.isSafeMode();
- mItems.clear();
- mAppWidgets.clear();
- mFolders.clear();
+ sItems.clear();
+ sAppWidgets.clear();
+ sFolders.clear();
+ sItemsIdMap.clear();
final ArrayList<Long> itemsToRemove = new ArrayList<Long>();
@@ -834,15 +911,16 @@ public class LauncherModel extends BroadcastReceiver {
switch (container) {
case LauncherSettings.Favorites.CONTAINER_DESKTOP:
- mItems.add(info);
+ sItems.add(info);
break;
default:
// Item is in a user folder
FolderInfo folderInfo =
- findOrMakeFolder(mFolders, container);
+ findOrMakeFolder(sFolders, container);
folderInfo.add(info);
break;
}
+ sItemsIdMap.put(info.id, info);
// now that we've loaded everthing re-save it with the
// icon in case it disappears somehow.
@@ -861,7 +939,7 @@ public class LauncherModel extends BroadcastReceiver {
case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
id = c.getLong(idIndex);
- FolderInfo folderInfo = findOrMakeFolder(mFolders, id);
+ FolderInfo folderInfo = findOrMakeFolder(sFolders, id);
folderInfo.title = c.getString(titleIndex);
folderInfo.id = id;
@@ -877,11 +955,12 @@ public class LauncherModel extends BroadcastReceiver {
}
switch (container) {
case LauncherSettings.Favorites.CONTAINER_DESKTOP:
- mItems.add(folderInfo);
+ sItems.add(folderInfo);
break;
}
- mFolders.put(folderInfo.id, folderInfo);
+ sItemsIdMap.put(folderInfo.id, folderInfo);
+ sFolders.put(folderInfo.id, folderInfo);
break;
case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
@@ -918,8 +997,8 @@ public class LauncherModel extends BroadcastReceiver {
if (!checkItemPlacement(occupied, appWidgetInfo)) {
break;
}
-
- mAppWidgets.add(appWidgetInfo);
+ sItemsIdMap.put(appWidgetInfo.id, appWidgetInfo);
+ sAppWidgets.add(appWidgetInfo);
}
break;
}
@@ -993,7 +1072,7 @@ public class LauncherModel extends BroadcastReceiver {
}
});
// Add the items to the workspace.
- N = mItems.size();
+ N = sItems.size();
for (int i=0; i<N; i+=ITEMS_CHUNK) {
final int start = i;
final int chunkSize = (i+ITEMS_CHUNK <= N) ? ITEMS_CHUNK : (N-i);
@@ -1001,7 +1080,7 @@ public class LauncherModel extends BroadcastReceiver {
public void run() {
Callbacks callbacks = tryGetCallbacks(oldCallbacks);
if (callbacks != null) {
- callbacks.bindItems(mItems, start, start+chunkSize);
+ callbacks.bindItems(sItems, start, start+chunkSize);
}
}
});
@@ -1010,7 +1089,7 @@ public class LauncherModel extends BroadcastReceiver {
public void run() {
Callbacks callbacks = tryGetCallbacks(oldCallbacks);
if (callbacks != null) {
- callbacks.bindFolders(mFolders);
+ callbacks.bindFolders(sFolders);
}
}
});
@@ -1028,10 +1107,10 @@ public class LauncherModel extends BroadcastReceiver {
// is just a hint for the order, and if it's wrong, we'll be okay.
// TODO: instead, we should have that push the current screen into here.
final int currentScreen = oldCallbacks.getCurrentWorkspaceScreen();
- N = mAppWidgets.size();
+ N = sAppWidgets.size();
// once for the current screen
for (int i=0; i<N; i++) {
- final LauncherAppWidgetInfo widget = mAppWidgets.get(i);
+ final LauncherAppWidgetInfo widget = sAppWidgets.get(i);
if (widget.screen == currentScreen) {
mHandler.post(new Runnable() {
public void run() {
@@ -1045,7 +1124,7 @@ public class LauncherModel extends BroadcastReceiver {
}
// once for the other screens
for (int i=0; i<N; i++) {
- final LauncherAppWidgetInfo widget = mAppWidgets.get(i);
+ final LauncherAppWidgetInfo widget = sAppWidgets.get(i);
if (widget.screen != currentScreen) {
mHandler.post(new Runnable() {
public void run() {
@@ -1238,7 +1317,7 @@ public class LauncherModel extends BroadcastReceiver {
Log.d(TAG, "mLoaderTask.mIsLaunching=" + mIsLaunching);
Log.d(TAG, "mLoaderTask.mStopped=" + mStopped);
Log.d(TAG, "mLoaderTask.mLoadAndBindStepFinished=" + mLoadAndBindStepFinished);
- Log.d(TAG, "mItems size=" + mItems.size());
+ Log.d(TAG, "mItems size=" + sItems.size());
}
}
diff --git a/src/com/android/launcher2/LauncherProvider.java b/src/com/android/launcher2/LauncherProvider.java
index a02e4496a..5ffd9844f 100644
--- a/src/com/android/launcher2/LauncherProvider.java
+++ b/src/com/android/launcher2/LauncherProvider.java
@@ -32,6 +32,7 @@ import android.content.res.XmlResourceParser;
import android.content.res.TypedArray;
import android.content.pm.PackageManager;
import android.content.pm.ActivityInfo;
+import android.content.SharedPreferences;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteStatement;
@@ -80,11 +81,12 @@ public class LauncherProvider extends ContentProvider {
static final Uri CONTENT_APPWIDGET_RESET_URI =
Uri.parse("content://" + AUTHORITY + "/appWidgetReset");
- private SQLiteOpenHelper mOpenHelper;
+ private DatabaseHelper mOpenHelper;
@Override
public boolean onCreate() {
mOpenHelper = new DatabaseHelper(getContext());
+ ((LauncherApplication) getContext()).setLauncherProvider(this);
return true;
}
@@ -113,12 +115,20 @@ public class LauncherProvider extends ContentProvider {
return result;
}
+ private static long dbInsertAndCheck(DatabaseHelper helper,
+ SQLiteDatabase db, String table, String nullColumnHack, ContentValues values) {
+ if (!values.containsKey(LauncherSettings.Favorites._ID)) {
+ throw new RuntimeException("Error: attempting to add item without specifying an id");
+ }
+ return db.insert(table, nullColumnHack, values);
+ }
+
@Override
public Uri insert(Uri uri, ContentValues initialValues) {
SqlArguments args = new SqlArguments(uri);
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- final long rowId = db.insert(args.table, null, initialValues);
+ final long rowId = dbInsertAndCheck(mOpenHelper, db, args.table, null, initialValues);
if (rowId <= 0) return null;
uri = ContentUris.withAppendedId(uri, rowId);
@@ -136,7 +146,9 @@ public class LauncherProvider extends ContentProvider {
try {
int numValues = values.length;
for (int i = 0; i < numValues; i++) {
- if (db.insert(args.table, null, values[i]) < 0) return 0;
+ if (dbInsertAndCheck(mOpenHelper, db, args.table, null, values[i]) < 0) {
+ return 0;
+ }
}
db.setTransactionSuccessful();
} finally {
@@ -176,6 +188,10 @@ public class LauncherProvider extends ContentProvider {
}
}
+ public long generateNewId() {
+ return mOpenHelper.generateNewId();
+ }
+
private static class DatabaseHelper extends SQLiteOpenHelper {
private static final String TAG_FAVORITES = "favorites";
private static final String TAG_FAVORITE = "favorite";
@@ -186,11 +202,13 @@ public class LauncherProvider extends ContentProvider {
private final Context mContext;
private final AppWidgetHost mAppWidgetHost;
+ private long mMaxId = -1;
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
mContext = context;
mAppWidgetHost = new AppWidgetHost(context, Launcher.APPWIDGET_HOST_ID);
+ mMaxId = initializeMaxId(getWritableDatabase());
}
/**
@@ -207,7 +225,9 @@ public class LauncherProvider extends ContentProvider {
@Override
public void onCreate(SQLiteDatabase db) {
if (LOGD) Log.d(TAG, "creating new launcher database");
-
+
+ mMaxId = 1;
+
db.execSQL("CREATE TABLE favorites (" +
"_id INTEGER PRIMARY KEY," +
"title TEXT," +
@@ -253,7 +273,7 @@ public class LauncherProvider extends ContentProvider {
try {
cursor = resolver.query(uri, null, null, null, null);
} catch (Exception e) {
- // Ignore
+ // Ignore
}
// We already have a favorites database in the old provider
@@ -321,7 +341,7 @@ public class LauncherProvider extends ContentProvider {
try {
int numValues = rows.length;
for (i = 0; i < numValues; i++) {
- if (db.insert(TABLE_FAVORITES, null, rows[i]) < 0) {
+ if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, rows[i]) < 0) {
return 0;
} else {
total++;
@@ -535,7 +555,36 @@ public class LauncherProvider extends ContentProvider {
c.close();
}
}
-
+ }
+
+ // Generates a new ID to use for an object in your database. This method should be only
+ // called from the main UI thread. As an exception, we do call it when we call the
+ // constructor from the worker thread; however, this doesn't extend until after the
+ // constructor is called, and we only pass a reference to LauncherProvider to LauncherApp
+ // after that point
+ public long generateNewId() {
+ if (mMaxId < 0) {
+ throw new RuntimeException("Error: max id was not initialized");
+ }
+ mMaxId += 1;
+ return mMaxId;
+ }
+
+ private long initializeMaxId(SQLiteDatabase db) {
+ Cursor c = db.rawQuery("SELECT MAX(_id) FROM favorites", null);
+
+ // get the result
+ final int maxIdIndex = 0;
+ long id = -1;
+ if (c != null && c.moveToNext()) {
+ id = c.getLong(maxIdIndex);
+ }
+
+ if (id == -1) {
+ throw new RuntimeException("Error: could not query max id");
+ }
+
+ return id;
}
/**
@@ -712,7 +761,8 @@ public class LauncherProvider extends ContentProvider {
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);
+ values.put(Favorites._ID, generateNewId());
+ dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values);
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "Unable to add favorite: " + packageName +
"/" + className, e);
@@ -804,7 +854,8 @@ public class LauncherProvider extends ContentProvider {
values.put(Favorites.SPANX, spanX);
values.put(Favorites.SPANY, spanY);
values.put(Favorites.APPWIDGET_ID, appWidgetId);
- db.insert(TABLE_FAVORITES, null, values);
+ values.put(Favorites._ID, generateNewId());
+ dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values);
allocatedAppWidgets = true;
@@ -847,8 +898,8 @@ public class LauncherProvider extends ContentProvider {
values.put(Favorites.ICON_TYPE, Favorites.ICON_TYPE_RESOURCE);
values.put(Favorites.ICON_PACKAGE, mContext.getPackageName());
values.put(Favorites.ICON_RESOURCE, r.getResourceName(iconResId));
-
- db.insert(TABLE_FAVORITES, null, values);
+ values.put(Favorites._ID, generateNewId());
+ dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values);
return true;
}