131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project/* 231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * you may not use this file except in compliance with the License. 631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * You may obtain a copy of the License at 731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 1031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 1131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 1231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * See the License for the specific language governing permissions and 1431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * limitations under the License. 1531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 1631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 17a5902524d4403885eb4c50360bf3465c6be796efJoe Onoratopackage com.android.launcher2; 1831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 19cd8fec02810ac2d7ca97c4cbb41e37dace832ecbBjorn Bringertimport android.app.SearchManager; 207376faefbbcbe30cc4e3f706ab95c254a4707d98The Android Open Source Projectimport android.appwidget.AppWidgetHost; 21b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleronimport android.appwidget.AppWidgetManager; 22cd8fec02810ac2d7ca97c4cbb41e37dace832ecbBjorn Bringertimport android.appwidget.AppWidgetProviderInfo; 23228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohenimport android.content.ComponentName; 2431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.ContentProvider; 25228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohenimport android.content.ContentResolver; 26228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohenimport android.content.ContentUris; 2731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.ContentValues; 28228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohenimport android.content.Context; 2931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.content.Intent; 30b85f8a44b51258f22938773ca30dd85845345010Michael Jurkaimport android.content.SharedPreferences; 31228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohenimport android.content.pm.ActivityInfo; 32228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohenimport android.content.pm.PackageManager; 33b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleronimport android.content.res.Resources; 34f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Projectimport android.content.res.TypedArray; 35228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohenimport android.content.res.XmlResourceParser; 3631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.database.Cursor; 3731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.database.SQLException; 38228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohenimport android.database.sqlite.SQLiteDatabase; 39228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohenimport android.database.sqlite.SQLiteOpenHelper; 40228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohenimport android.database.sqlite.SQLiteQueryBuilder; 41228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohenimport android.database.sqlite.SQLiteStatement; 420589f0f66ce498512c6ee47482c649d88294c9d0Joe Onoratoimport android.graphics.Bitmap; 430589f0f66ce498512c6ee47482c649d88294c9d0Joe Onoratoimport android.graphics.BitmapFactory; 4431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.net.Uri; 45b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chungimport android.os.Bundle; 46374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasaniimport android.os.UserManager; 4731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectimport android.provider.Settings; 48228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohenimport android.text.TextUtils; 49228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohenimport android.util.AttributeSet; 50228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohenimport android.util.Log; 51228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohenimport android.util.Xml; 52094fc7ac6daef2463a8885499ae80bcf1ae7f849Dianne Hackborn 538b805b17158886035b38261eb611d8641701ae43Michael Jurkaimport com.android.launcher.R; 548b805b17158886035b38261eb611d8641701ae43Michael Jurkaimport com.android.launcher2.LauncherSettings.Favorites; 558b805b17158886035b38261eb611d8641701ae43Michael Jurka 568b805b17158886035b38261eb611d8641701ae43Michael Jurkaimport org.xmlpull.v1.XmlPullParser; 578b805b17158886035b38261eb611d8641701ae43Michael Jurkaimport org.xmlpull.v1.XmlPullParserException; 588b805b17158886035b38261eb611d8641701ae43Michael Jurka 59f627f9cd1fb376c206c8a68d052fc36ebc0aaa1dJason Monkimport java.io.File; 60228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohenimport java.io.IOException; 61228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohenimport java.net.URISyntaxException; 62228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohenimport java.util.ArrayList; 63228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohenimport java.util.List; 64edcce099c98a6c40d10109ac092ab50f9d2668f3Romain Guy 6531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Projectpublic class LauncherProvider extends ContentProvider { 66a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato private static final String TAG = "Launcher.LauncherProvider"; 67a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato private static final boolean LOGD = false; 6831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 6931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project private static final String DATABASE_NAME = "launcher.db"; 703d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung 71374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani private static final int DATABASE_VERSION = 13; 7231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 73a5902524d4403885eb4c50360bf3465c6be796efJoe Onorato static final String AUTHORITY = "com.android.launcher2.settings"; 743d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung 7531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project static final String TABLE_FAVORITES = "favorites"; 7631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project static final String PARAMETER_NOTIFY = "notify"; 77b85f8a44b51258f22938773ca30dd85845345010Michael Jurka static final String DB_CREATED_BUT_DEFAULT_WORKSPACE_NOT_LOADED = 78b85f8a44b51258f22938773ca30dd85845345010Michael Jurka "DB_CREATED_BUT_DEFAULT_WORKSPACE_NOT_LOADED"; 7945355c4596f396d7e7247e91de850646356bd104Michael Jurka static final String DEFAULT_WORKSPACE_RESOURCE_ID = 8045355c4596f396d7e7247e91de850646356bd104Michael Jurka "DEFAULT_WORKSPACE_RESOURCE_ID"; 8131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 82b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung private static final String ACTION_APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE = 83b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung "com.android.launcher.action.APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE"; 84b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung 852bbcae19224447c018b87bccff2b7f5e650d18d8Jeffrey Sharkey /** 8673b979d8c141c7ceac82dad7c5b271a6a42afa67Romain Guy * {@link Uri} triggered at any registered {@link android.database.ContentObserver} when 872bbcae19224447c018b87bccff2b7f5e650d18d8Jeffrey Sharkey * {@link AppWidgetHost#deleteHost()} is called during database creation. 882bbcae19224447c018b87bccff2b7f5e650d18d8Jeffrey Sharkey * Use this to recall {@link AppWidgetHost#startListening()} if needed. 892bbcae19224447c018b87bccff2b7f5e650d18d8Jeffrey Sharkey */ 902bbcae19224447c018b87bccff2b7f5e650d18d8Jeffrey Sharkey static final Uri CONTENT_APPWIDGET_RESET_URI = 912bbcae19224447c018b87bccff2b7f5e650d18d8Jeffrey Sharkey Uri.parse("content://" + AUTHORITY + "/appWidgetReset"); 92c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann 93a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka private DatabaseHelper mOpenHelper; 9431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 9531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project @Override 9631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public boolean onCreate() { 9731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project mOpenHelper = new DatabaseHelper(getContext()); 98a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka ((LauncherApplication) getContext()).setLauncherProvider(this); 9931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project return true; 10031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 10131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 10231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project @Override 10331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public String getType(Uri uri) { 10431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project SqlArguments args = new SqlArguments(uri, null, null); 10531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (TextUtils.isEmpty(args.where)) { 10631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project return "vnd.android.cursor.dir/" + args.table; 10731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } else { 10831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project return "vnd.android.cursor.item/" + args.table; 10931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 11031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 11131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 11231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project @Override 11331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public Cursor query(Uri uri, String[] projection, String selection, 11431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project String[] selectionArgs, String sortOrder) { 11531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 11631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project SqlArguments args = new SqlArguments(uri, selection, selectionArgs); 11731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); 11831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project qb.setTables(args.table); 11931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 12073b979d8c141c7ceac82dad7c5b271a6a42afa67Romain Guy SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 12131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project Cursor result = qb.query(db, projection, args.where, args.args, null, null, sortOrder); 12231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project result.setNotificationUri(getContext().getContentResolver(), uri); 12331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 12431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project return result; 12531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 12631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 127a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka private static long dbInsertAndCheck(DatabaseHelper helper, 128a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka SQLiteDatabase db, String table, String nullColumnHack, ContentValues values) { 129a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka if (!values.containsKey(LauncherSettings.Favorites._ID)) { 130a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka throw new RuntimeException("Error: attempting to add item without specifying an id"); 131a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka } 132a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka return db.insert(table, nullColumnHack, values); 133a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka } 134a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka 135228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen private static void deleteId(SQLiteDatabase db, long id) { 136228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen Uri uri = LauncherSettings.Favorites.getContentUri(id, false); 137228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen SqlArguments args = new SqlArguments(uri, null, null); 138228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen db.delete(args.table, args.where, args.args); 139228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen } 140228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen 14131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project @Override 14231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public Uri insert(Uri uri, ContentValues initialValues) { 14331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project SqlArguments args = new SqlArguments(uri); 14431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 14531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 146a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka final long rowId = dbInsertAndCheck(mOpenHelper, db, args.table, null, initialValues); 14731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (rowId <= 0) return null; 14831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 14931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project uri = ContentUris.withAppendedId(uri, rowId); 15031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project sendNotify(uri); 15131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 15231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project return uri; 15331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 15431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 15531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project @Override 15631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public int bulkInsert(Uri uri, ContentValues[] values) { 15731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project SqlArguments args = new SqlArguments(uri); 15831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 15931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 16031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project db.beginTransaction(); 16131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project try { 16231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project int numValues = values.length; 16331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project for (int i = 0; i < numValues; i++) { 164a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka if (dbInsertAndCheck(mOpenHelper, db, args.table, null, values[i]) < 0) { 165a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka return 0; 166a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka } 16731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 16831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project db.setTransactionSuccessful(); 16931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } finally { 17031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project db.endTransaction(); 17131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 17231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 17331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project sendNotify(uri); 17431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project return values.length; 17531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 17631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 17731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project @Override 17831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public int delete(Uri uri, String selection, String[] selectionArgs) { 17931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project SqlArguments args = new SqlArguments(uri, selection, selectionArgs); 18031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 18131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 18231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project int count = db.delete(args.table, args.where, args.args); 18331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (count > 0) sendNotify(uri); 18431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 18531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project return count; 18631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 18731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 18831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project @Override 18931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 19031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project SqlArguments args = new SqlArguments(uri, selection, selectionArgs); 19131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 19231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 19331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project int count = db.update(args.table, values, args.where, args.args); 19431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (count > 0) sendNotify(uri); 19531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 19631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project return count; 19731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 19831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 19931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project private void sendNotify(Uri uri) { 20031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project String notify = uri.getQueryParameter(PARAMETER_NOTIFY); 20131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (notify == null || "true".equals(notify)) { 20231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project getContext().getContentResolver().notifyChange(uri, null); 20331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 20431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 20531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 206a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka public long generateNewId() { 207a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka return mOpenHelper.generateNewId(); 208a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka } 209a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka 2105524b4957fc7c1c858037327429411efdb8fe7d6Brian Muramatsu /** 2115524b4957fc7c1c858037327429411efdb8fe7d6Brian Muramatsu * @param workspaceResId that can be 0 to use default or non-zero for specific resource 2125524b4957fc7c1c858037327429411efdb8fe7d6Brian Muramatsu */ 213f627f9cd1fb376c206c8a68d052fc36ebc0aaa1dJason Monk synchronized public void loadDefaultFavoritesIfNecessary(int origWorkspaceResId, 214f627f9cd1fb376c206c8a68d052fc36ebc0aaa1dJason Monk boolean overridePrevious) { 215b85f8a44b51258f22938773ca30dd85845345010Michael Jurka String spKey = LauncherApplication.getSharedPreferencesKey(); 216b85f8a44b51258f22938773ca30dd85845345010Michael Jurka SharedPreferences sp = getContext().getSharedPreferences(spKey, Context.MODE_PRIVATE); 217f627f9cd1fb376c206c8a68d052fc36ebc0aaa1dJason Monk boolean dbCreatedNoWorkspace = 218f627f9cd1fb376c206c8a68d052fc36ebc0aaa1dJason Monk sp.getBoolean(DB_CREATED_BUT_DEFAULT_WORKSPACE_NOT_LOADED, false); 219f627f9cd1fb376c206c8a68d052fc36ebc0aaa1dJason Monk if (dbCreatedNoWorkspace || overridePrevious) { 22045355c4596f396d7e7247e91de850646356bd104Michael Jurka int workspaceResId = origWorkspaceResId; 22145355c4596f396d7e7247e91de850646356bd104Michael Jurka 2225524b4957fc7c1c858037327429411efdb8fe7d6Brian Muramatsu // Use default workspace resource if none provided 2235524b4957fc7c1c858037327429411efdb8fe7d6Brian Muramatsu if (workspaceResId == 0) { 22445355c4596f396d7e7247e91de850646356bd104Michael Jurka workspaceResId = sp.getInt(DEFAULT_WORKSPACE_RESOURCE_ID, R.xml.default_workspace); 2255524b4957fc7c1c858037327429411efdb8fe7d6Brian Muramatsu } 2265524b4957fc7c1c858037327429411efdb8fe7d6Brian Muramatsu 227b85f8a44b51258f22938773ca30dd85845345010Michael Jurka // Populate favorites table with initial favorites 228b85f8a44b51258f22938773ca30dd85845345010Michael Jurka SharedPreferences.Editor editor = sp.edit(); 229b85f8a44b51258f22938773ca30dd85845345010Michael Jurka editor.remove(DB_CREATED_BUT_DEFAULT_WORKSPACE_NOT_LOADED); 23045355c4596f396d7e7247e91de850646356bd104Michael Jurka if (origWorkspaceResId != 0) { 23145355c4596f396d7e7247e91de850646356bd104Michael Jurka editor.putInt(DEFAULT_WORKSPACE_RESOURCE_ID, origWorkspaceResId); 23245355c4596f396d7e7247e91de850646356bd104Michael Jurka } 233f627f9cd1fb376c206c8a68d052fc36ebc0aaa1dJason Monk if (!dbCreatedNoWorkspace && overridePrevious) { 234f627f9cd1fb376c206c8a68d052fc36ebc0aaa1dJason Monk if (LOGD) Log.d(TAG, "Clearing old launcher database"); 235f627f9cd1fb376c206c8a68d052fc36ebc0aaa1dJason Monk // Workspace has already been loaded, clear the database. 236f627f9cd1fb376c206c8a68d052fc36ebc0aaa1dJason Monk deleteDatabase(); 237f627f9cd1fb376c206c8a68d052fc36ebc0aaa1dJason Monk } 2385524b4957fc7c1c858037327429411efdb8fe7d6Brian Muramatsu mOpenHelper.loadFavorites(mOpenHelper.getWritableDatabase(), workspaceResId); 239b85f8a44b51258f22938773ca30dd85845345010Michael Jurka editor.commit(); 240b85f8a44b51258f22938773ca30dd85845345010Michael Jurka } 241b85f8a44b51258f22938773ca30dd85845345010Michael Jurka } 242b85f8a44b51258f22938773ca30dd85845345010Michael Jurka 243f627f9cd1fb376c206c8a68d052fc36ebc0aaa1dJason Monk public void deleteDatabase() { 244f627f9cd1fb376c206c8a68d052fc36ebc0aaa1dJason Monk // Are you sure? (y/n) 245f627f9cd1fb376c206c8a68d052fc36ebc0aaa1dJason Monk final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 246f627f9cd1fb376c206c8a68d052fc36ebc0aaa1dJason Monk final File dbFile = new File(db.getPath()); 247f627f9cd1fb376c206c8a68d052fc36ebc0aaa1dJason Monk mOpenHelper.close(); 248f627f9cd1fb376c206c8a68d052fc36ebc0aaa1dJason Monk if (dbFile.exists()) { 249f627f9cd1fb376c206c8a68d052fc36ebc0aaa1dJason Monk SQLiteDatabase.deleteDatabase(dbFile); 250f627f9cd1fb376c206c8a68d052fc36ebc0aaa1dJason Monk } 251f627f9cd1fb376c206c8a68d052fc36ebc0aaa1dJason Monk mOpenHelper = new DatabaseHelper(getContext()); 252f627f9cd1fb376c206c8a68d052fc36ebc0aaa1dJason Monk } 253f627f9cd1fb376c206c8a68d052fc36ebc0aaa1dJason Monk 25431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project private static class DatabaseHelper extends SQLiteOpenHelper { 25531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project private static final String TAG_FAVORITES = "favorites"; 25631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project private static final String TAG_FAVORITE = "favorite"; 257f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project private static final String TAG_CLOCK = "clock"; 258f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project private static final String TAG_SEARCH = "search"; 259b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron private static final String TAG_APPWIDGET = "appwidget"; 260b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron private static final String TAG_SHORTCUT = "shortcut"; 261228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen private static final String TAG_FOLDER = "folder"; 262b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung private static final String TAG_EXTRA = "extra"; 2633d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung 26431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project private final Context mContext; 2657376faefbbcbe30cc4e3f706ab95c254a4707d98The Android Open Source Project private final AppWidgetHost mAppWidgetHost; 266a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka private long mMaxId = -1; 26731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 26831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project DatabaseHelper(Context context) { 26931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project super(context, DATABASE_NAME, null, DATABASE_VERSION); 27031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project mContext = context; 2717376faefbbcbe30cc4e3f706ab95c254a4707d98The Android Open Source Project mAppWidgetHost = new AppWidgetHost(context, Launcher.APPWIDGET_HOST_ID); 2723d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung 2733d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung // In the case where neither onCreate nor onUpgrade gets called, we read the maxId from 2743d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung // the DB here 2753d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung if (mMaxId == -1) { 2763d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung mMaxId = initializeMaxId(getWritableDatabase()); 2773d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung } 27831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 27931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 2802bbcae19224447c018b87bccff2b7f5e650d18d8Jeffrey Sharkey /** 2812bbcae19224447c018b87bccff2b7f5e650d18d8Jeffrey Sharkey * Send notification that we've deleted the {@link AppWidgetHost}, 2822bbcae19224447c018b87bccff2b7f5e650d18d8Jeffrey Sharkey * probably as part of the initial database creation. The receiver may 2832bbcae19224447c018b87bccff2b7f5e650d18d8Jeffrey Sharkey * want to re-call {@link AppWidgetHost#startListening()} to ensure 2842bbcae19224447c018b87bccff2b7f5e650d18d8Jeffrey Sharkey * callbacks are correctly set. 2852bbcae19224447c018b87bccff2b7f5e650d18d8Jeffrey Sharkey */ 2862bbcae19224447c018b87bccff2b7f5e650d18d8Jeffrey Sharkey private void sendAppWidgetResetNotify() { 2872bbcae19224447c018b87bccff2b7f5e650d18d8Jeffrey Sharkey final ContentResolver resolver = mContext.getContentResolver(); 2882bbcae19224447c018b87bccff2b7f5e650d18d8Jeffrey Sharkey resolver.notifyChange(CONTENT_APPWIDGET_RESET_URI, null); 2892bbcae19224447c018b87bccff2b7f5e650d18d8Jeffrey Sharkey } 2902bbcae19224447c018b87bccff2b7f5e650d18d8Jeffrey Sharkey 29131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project @Override 29231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public void onCreate(SQLiteDatabase db) { 293a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato if (LOGD) Log.d(TAG, "creating new launcher database"); 294a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka 295a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka mMaxId = 1; 2960fb10008be0b5a44155f90f06b8a8a6cf77a83f6Amith Yamasani final UserManager um = 2970fb10008be0b5a44155f90f06b8a8a6cf77a83f6Amith Yamasani (UserManager) mContext.getSystemService(Context.USER_SERVICE); 2980fb10008be0b5a44155f90f06b8a8a6cf77a83f6Amith Yamasani // Default profileId to the serial number of this user. 2990fb10008be0b5a44155f90f06b8a8a6cf77a83f6Amith Yamasani long userSerialNumber = um.getSerialNumberForUser( 3000fb10008be0b5a44155f90f06b8a8a6cf77a83f6Amith Yamasani android.os.Process.myUserHandle()); 301a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka 30231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project db.execSQL("CREATE TABLE favorites (" + 30331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project "_id INTEGER PRIMARY KEY," + 30431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project "title TEXT," + 30531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project "intent TEXT," + 30631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project "container INTEGER," + 30731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project "screen INTEGER," + 30831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project "cellX INTEGER," + 30931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project "cellY INTEGER," + 31031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project "spanX INTEGER," + 31131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project "spanY INTEGER," + 31231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project "itemType INTEGER," + 313ca9475f0403d9c0e843d5c189575068a386b2eb6The Android Open Source Project "appWidgetId INTEGER NOT NULL DEFAULT -1," + 31431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project "isShortcut INTEGER," + 31531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project "iconType INTEGER," + 31631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project "iconPackage TEXT," + 31731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project "iconResource TEXT," + 31831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project "icon BLOB," + 31931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project "uri TEXT," + 320374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani "displayMode INTEGER," + 3210fb10008be0b5a44155f90f06b8a8a6cf77a83f6Amith Yamasani "profileId INTEGER DEFAULT " + userSerialNumber + 32231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project ");"); 32331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 3247376faefbbcbe30cc4e3f706ab95c254a4707d98The Android Open Source Project // Database was just created, so wipe any previous widgets 3257376faefbbcbe30cc4e3f706ab95c254a4707d98The Android Open Source Project if (mAppWidgetHost != null) { 3267376faefbbcbe30cc4e3f706ab95c254a4707d98The Android Open Source Project mAppWidgetHost.deleteHost(); 3272bbcae19224447c018b87bccff2b7f5e650d18d8Jeffrey Sharkey sendAppWidgetResetNotify(); 32831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 3293d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung 33031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (!convertDatabase(db)) { 331b85f8a44b51258f22938773ca30dd85845345010Michael Jurka // Set a shared pref so that we know we need to load the default workspace later 332b85f8a44b51258f22938773ca30dd85845345010Michael Jurka setFlagToLoadDefaultWorkspaceLater(); 33331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 33431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 33531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 336b85f8a44b51258f22938773ca30dd85845345010Michael Jurka private void setFlagToLoadDefaultWorkspaceLater() { 337b85f8a44b51258f22938773ca30dd85845345010Michael Jurka String spKey = LauncherApplication.getSharedPreferencesKey(); 338b85f8a44b51258f22938773ca30dd85845345010Michael Jurka SharedPreferences sp = mContext.getSharedPreferences(spKey, Context.MODE_PRIVATE); 339b85f8a44b51258f22938773ca30dd85845345010Michael Jurka SharedPreferences.Editor editor = sp.edit(); 340b85f8a44b51258f22938773ca30dd85845345010Michael Jurka editor.putBoolean(DB_CREATED_BUT_DEFAULT_WORKSPACE_NOT_LOADED, true); 341b85f8a44b51258f22938773ca30dd85845345010Michael Jurka editor.commit(); 342b85f8a44b51258f22938773ca30dd85845345010Michael Jurka } 343b85f8a44b51258f22938773ca30dd85845345010Michael Jurka 34431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project private boolean convertDatabase(SQLiteDatabase db) { 345a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato if (LOGD) Log.d(TAG, "converting database from an older format, but not onUpgrade"); 34631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project boolean converted = false; 34731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 34831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final Uri uri = Uri.parse("content://" + Settings.AUTHORITY + 34931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project "/old_favorites?notify=true"); 35031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final ContentResolver resolver = mContext.getContentResolver(); 35131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project Cursor cursor = null; 35231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 35331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project try { 35431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project cursor = resolver.query(uri, null, null, null, null); 35531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } catch (Exception e) { 356a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka // Ignore 35731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 35831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 35931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project // We already have a favorites database in the old provider 36031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (cursor != null && cursor.getCount() > 0) { 36131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project try { 36231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project converted = copyFromCursor(db, cursor) > 0; 36331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } finally { 36431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project cursor.close(); 36531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 36631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 36731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (converted) { 36831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project resolver.delete(uri, null, null); 36931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 37031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 371c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann 37231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (converted) { 3737376faefbbcbe30cc4e3f706ab95c254a4707d98The Android Open Source Project // Convert widgets from this import into widgets 374a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato if (LOGD) Log.d(TAG, "converted and now triggering widget upgrade"); 37531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project convertWidgets(db); 37631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 37731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 37831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project return converted; 37931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 38031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 38131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project private int copyFromCursor(SQLiteDatabase db, Cursor c) { 38273b979d8c141c7ceac82dad7c5b271a6a42afa67Romain Guy final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID); 38331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final int intentIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT); 38431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final int titleIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE); 38531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final int iconTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_TYPE); 38631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final int iconIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON); 38731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final int iconPackageIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_PACKAGE); 38831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final int iconResourceIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_RESOURCE); 38931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER); 39031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE); 39131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN); 39231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX); 39331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY); 39431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final int uriIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.URI); 39531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final int displayModeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.DISPLAY_MODE); 39631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 39731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project ContentValues[] rows = new ContentValues[c.getCount()]; 39831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project int i = 0; 39931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project while (c.moveToNext()) { 40031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project ContentValues values = new ContentValues(c.getColumnCount()); 40173b979d8c141c7ceac82dad7c5b271a6a42afa67Romain Guy values.put(LauncherSettings.Favorites._ID, c.getLong(idIndex)); 40231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project values.put(LauncherSettings.Favorites.INTENT, c.getString(intentIndex)); 40331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project values.put(LauncherSettings.Favorites.TITLE, c.getString(titleIndex)); 40431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project values.put(LauncherSettings.Favorites.ICON_TYPE, c.getInt(iconTypeIndex)); 40531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project values.put(LauncherSettings.Favorites.ICON, c.getBlob(iconIndex)); 40631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project values.put(LauncherSettings.Favorites.ICON_PACKAGE, c.getString(iconPackageIndex)); 40731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project values.put(LauncherSettings.Favorites.ICON_RESOURCE, c.getString(iconResourceIndex)); 40831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project values.put(LauncherSettings.Favorites.CONTAINER, c.getInt(containerIndex)); 40931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project values.put(LauncherSettings.Favorites.ITEM_TYPE, c.getInt(itemTypeIndex)); 4107376faefbbcbe30cc4e3f706ab95c254a4707d98The Android Open Source Project values.put(LauncherSettings.Favorites.APPWIDGET_ID, -1); 41131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project values.put(LauncherSettings.Favorites.SCREEN, c.getInt(screenIndex)); 41231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project values.put(LauncherSettings.Favorites.CELLX, c.getInt(cellXIndex)); 41331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project values.put(LauncherSettings.Favorites.CELLY, c.getInt(cellYIndex)); 41431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project values.put(LauncherSettings.Favorites.URI, c.getString(uriIndex)); 41531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project values.put(LauncherSettings.Favorites.DISPLAY_MODE, c.getInt(displayModeIndex)); 41631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project rows[i++] = values; 41731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 41831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 41931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project db.beginTransaction(); 42031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project int total = 0; 42131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project try { 42231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project int numValues = rows.length; 42331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project for (i = 0; i < numValues; i++) { 424a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, rows[i]) < 0) { 42531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project return 0; 42631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } else { 42731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project total++; 42831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 42931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 43031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project db.setTransactionSuccessful(); 43131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } finally { 43231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project db.endTransaction(); 43331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 43431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 43531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project return total; 43631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 43731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 43831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project @Override 43931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 440a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato if (LOGD) Log.d(TAG, "onUpgrade triggered"); 441c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann 44231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project int version = oldVersion; 443ca9475f0403d9c0e843d5c189575068a386b2eb6The Android Open Source Project if (version < 3) { 444ca9475f0403d9c0e843d5c189575068a386b2eb6The Android Open Source Project // upgrade 1,2 -> 3 added appWidgetId column 44531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project db.beginTransaction(); 44631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project try { 4477376faefbbcbe30cc4e3f706ab95c254a4707d98The Android Open Source Project // Insert new column for holding appWidgetIds 44831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project db.execSQL("ALTER TABLE favorites " + 449ca9475f0403d9c0e843d5c189575068a386b2eb6The Android Open Source Project "ADD COLUMN appWidgetId INTEGER NOT NULL DEFAULT -1;"); 45031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project db.setTransactionSuccessful(); 451ca9475f0403d9c0e843d5c189575068a386b2eb6The Android Open Source Project version = 3; 45231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } catch (SQLException ex) { 45331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project // Old version remains, which means we wipe old data 454a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato Log.e(TAG, ex.getMessage(), ex); 45531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } finally { 45631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project db.endTransaction(); 45731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 458c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann 45931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project // Convert existing widgets only if table upgrade was successful 460ca9475f0403d9c0e843d5c189575068a386b2eb6The Android Open Source Project if (version == 3) { 46131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project convertWidgets(db); 46231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 46331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 46473b979d8c141c7ceac82dad7c5b271a6a42afa67Romain Guy 46573b979d8c141c7ceac82dad7c5b271a6a42afa67Romain Guy if (version < 4) { 4667eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy version = 4; 46773b979d8c141c7ceac82dad7c5b271a6a42afa67Romain Guy } 468c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann 469509cd6a656627187dae20fdbec2bad76dfe7fab6Romain Guy // Where's version 5? 470509cd6a656627187dae20fdbec2bad76dfe7fab6Romain Guy // - Donut and sholes on 2.0 shipped with version 4 of launcher1. 471509cd6a656627187dae20fdbec2bad76dfe7fab6Romain Guy // - Passion shipped on 2.1 with version 6 of launcher2 472509cd6a656627187dae20fdbec2bad76dfe7fab6Romain Guy // - Sholes shipped on 2.1r1 (aka Mr. 3) with version 5 of launcher 1 473509cd6a656627187dae20fdbec2bad76dfe7fab6Romain Guy // but version 5 on there was the updateContactsShortcuts change 474509cd6a656627187dae20fdbec2bad76dfe7fab6Romain Guy // which was version 6 in launcher 2 (first shipped on passion 2.1r1). 475509cd6a656627187dae20fdbec2bad76dfe7fab6Romain Guy // The updateContactsShortcuts change is idempotent, so running it twice 476509cd6a656627187dae20fdbec2bad76dfe7fab6Romain Guy // is okay so we'll do that when upgrading the devices that shipped with it. 477509cd6a656627187dae20fdbec2bad76dfe7fab6Romain Guy if (version < 6) { 4783a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron // We went from 3 to 5 screens. Move everything 1 to the right 4793a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron db.beginTransaction(); 4803a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron try { 4813a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron db.execSQL("UPDATE favorites SET screen=(screen + 1);"); 4823a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron db.setTransactionSuccessful(); 4833a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron } catch (SQLException ex) { 4843a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron // Old version remains, which means we wipe old data 485a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato Log.e(TAG, ex.getMessage(), ex); 4863a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron } finally { 4873a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron db.endTransaction(); 4883a2b3f2be58843d26549fb0ec6c6533627c7cd19Mike Cleron } 489c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann 490509cd6a656627187dae20fdbec2bad76dfe7fab6Romain Guy // We added the fast track. 4917eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy if (updateContactsShortcuts(db)) { 4927eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy version = 6; 4937eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy } 4947eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy } 4957984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert 4967984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert if (version < 7) { 4977984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert // Version 7 gets rid of the special search widget. 4987984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert convertWidgets(db); 4997984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert version = 7; 5007984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert } 5017984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert 5020589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato if (version < 8) { 5030589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato // Version 8 (froyo) has the icons all normalized. This should 5040589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato // already be the case in practice, but we now rely on it and don't 5050589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato // resample the images each time. 5060589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato normalizeIcons(db); 5070589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato version = 8; 5080589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato } 5090589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato 5103d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung if (version < 9) { 5113d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung // The max id is not yet set at this point (onUpgrade is triggered in the ctor 5123d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung // before it gets a change to get set, so we need to read it here when we use it) 5133d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung if (mMaxId == -1) { 5143d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung mMaxId = initializeMaxId(db); 5153d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung } 5163d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung 5173d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung // Add default hotseat icons 5186d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung loadFavorites(db, R.xml.update_workspace); 5193d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung version = 9; 5203d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung } 5213d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung 522d02402cb141d5f7838a10a400926e0dfcee2783fDaniel Lehmann // We bumped the version three time during JB, once to update the launch flags, once to 523d02402cb141d5f7838a10a400926e0dfcee2783fDaniel Lehmann // update the override for the default launch animation and once to set the mimetype 524d02402cb141d5f7838a10a400926e0dfcee2783fDaniel Lehmann // to improve startup performance 525d02402cb141d5f7838a10a400926e0dfcee2783fDaniel Lehmann if (version < 12) { 526c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann // Contact shortcuts need a different set of flags to be launched now 527c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann // The updateContactsShortcuts change is idempotent, so we can keep using it like 528c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann // back in the Donut days 529c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann updateContactsShortcuts(db); 530d02402cb141d5f7838a10a400926e0dfcee2783fDaniel Lehmann version = 12; 531c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann } 532c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann 533374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani if (version < 13) { 534374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani // Add userId column 535374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani if (addProfileColumn(db)) { 536374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani version = 13; 537374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani } 538374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani } 539374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani 54031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (version != DATABASE_VERSION) { 541a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato Log.w(TAG, "Destroying all old data."); 54231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project db.execSQL("DROP TABLE IF EXISTS " + TABLE_FAVORITES); 54331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project onCreate(db); 54431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 54531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 5467eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy 547374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani private boolean addProfileColumn(SQLiteDatabase db) { 548374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani db.beginTransaction(); 549374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani try { 550374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani final UserManager um = 551374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani (UserManager) mContext.getSystemService(Context.USER_SERVICE); 552374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani // Default to the serial number of this user, for older 553374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani // shortcuts. 554374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani long userSerialNumber = um.getSerialNumberForUser( 555374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani android.os.Process.myUserHandle()); 556374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani // Insert new column for holding user serial number 557374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani db.execSQL("ALTER TABLE favorites " + 558374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani "ADD COLUMN profileId INTEGER DEFAULT " 559374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani + userSerialNumber + ";"); 560374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani db.setTransactionSuccessful(); 561374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani return true; 562374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani } catch (SQLException ex) { 563374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani // Old version remains, which means we wipe old data 564374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani Log.e(TAG, ex.getMessage(), ex); 565374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani return false; 566374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani } finally { 567374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani db.endTransaction(); 568374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani } 569374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani } 570374753cabf05cde1ad669d07bde47e34fdcbe499Amith Yamasani 5717eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy private boolean updateContactsShortcuts(SQLiteDatabase db) { 5727eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy final String selectWhere = buildOrWhereString(Favorites.ITEM_TYPE, 5737eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy new int[] { Favorites.ITEM_TYPE_SHORTCUT }); 5747eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy 575c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann Cursor c = null; 576c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann final String actionQuickContact = "com.android.contacts.action.QUICK_CONTACT"; 5777eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy db.beginTransaction(); 5787eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy try { 5797eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy // Select and iterate through each matching widget 580c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann c = db.query(TABLE_FAVORITES, 581c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann new String[] { Favorites._ID, Favorites.INTENT }, 5827eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy selectWhere, null, null, null, null); 583c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann if (c == null) return false; 584c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann 5857eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy if (LOGD) Log.d(TAG, "found upgrade cursor count=" + c.getCount()); 586c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann 5877eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy final int idIndex = c.getColumnIndex(Favorites._ID); 5887eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy final int intentIndex = c.getColumnIndex(Favorites.INTENT); 589c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann 590c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann while (c.moveToNext()) { 5917eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy long favoriteId = c.getLong(idIndex); 5927eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy final String intentUri = c.getString(intentIndex); 5937eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy if (intentUri != null) { 5947eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy try { 595c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann final Intent intent = Intent.parseUri(intentUri, 0); 5967eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy android.util.Log.d("Home", intent.toString()); 5977eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy final Uri uri = intent.getData(); 598c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann if (uri != null) { 599c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann final String data = uri.toString(); 600c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann if ((Intent.ACTION_VIEW.equals(intent.getAction()) || 601c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann actionQuickContact.equals(intent.getAction())) && 602c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann (data.startsWith("content://contacts/people/") || 603c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann data.startsWith("content://com.android.contacts/" + 604c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann "contacts/lookup/"))) { 605c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann 606c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann final Intent newIntent = new Intent(actionQuickContact); 607c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann // When starting from the launcher, start in a new, cleared task 608c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann // CLEAR_WHEN_TASK_RESET cannot reset the root of a task, so we 609c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann // clear the whole thing preemptively here since 610c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann // QuickContactActivity will finish itself when launching other 611c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann // detail activities. 612c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | 613c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann Intent.FLAG_ACTIVITY_CLEAR_TASK); 6142672ff937ea7885d184679dfee9f355b7bf2fc7dWinson Chung newIntent.putExtra( 6152672ff937ea7885d184679dfee9f355b7bf2fc7dWinson Chung Launcher.INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION, true); 616c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann newIntent.setData(uri); 617d02402cb141d5f7838a10a400926e0dfcee2783fDaniel Lehmann // Determine the type and also put that in the shortcut 618d02402cb141d5f7838a10a400926e0dfcee2783fDaniel Lehmann // (that can speed up launch a bit) 619d02402cb141d5f7838a10a400926e0dfcee2783fDaniel Lehmann newIntent.setDataAndType(uri, newIntent.resolveType(mContext)); 620c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann 621c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann final ContentValues values = new ContentValues(); 622c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann values.put(LauncherSettings.Favorites.INTENT, 623c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann newIntent.toUri(0)); 624c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann 625c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann String updateWhere = Favorites._ID + "=" + favoriteId; 626c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann db.update(TABLE_FAVORITES, values, updateWhere, null); 627c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann } 6287eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy } 6297eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy } catch (RuntimeException ex) { 6307eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy Log.e(TAG, "Problem upgrading shortcut", ex); 6317eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy } catch (URISyntaxException e) { 632c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann Log.e(TAG, "Problem upgrading shortcut", e); 6337eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy } 6347eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy } 6357eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy } 636c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann 6377eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy db.setTransactionSuccessful(); 6387eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy } catch (SQLException ex) { 6397eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy Log.w(TAG, "Problem while upgrading contacts", ex); 6407eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy return false; 6417eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy } finally { 6427eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy db.endTransaction(); 6437eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy if (c != null) { 6447eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy c.close(); 6457eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy } 6467eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy } 6477eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy 6487eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy return true; 6497eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy } 6507eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy 6510589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato private void normalizeIcons(SQLiteDatabase db) { 6520589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato Log.d(TAG, "normalizing icons"); 6530589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato 654346e129456951b5db36a663d5601421e8019632eJoe Onorato db.beginTransaction(); 6550589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato Cursor c = null; 6569690b396d5f24a31ce8ffd9739f1f5d03a69bdceJoe Onorato SQLiteStatement update = null; 6570589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato try { 6580589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato boolean logged = false; 6599690b396d5f24a31ce8ffd9739f1f5d03a69bdceJoe Onorato update = db.compileStatement("UPDATE favorites " 660eaf77d6c3dafb1a9032c98de53e0de335f59af30Jeff Hamilton + "SET icon=? WHERE _id=?"); 6610589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato 6620589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato c = db.rawQuery("SELECT _id, icon FROM favorites WHERE iconType=" + 6630589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato Favorites.ICON_TYPE_BITMAP, null); 6640589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato 6650589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato final int idIndex = c.getColumnIndexOrThrow(Favorites._ID); 6660589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato final int iconIndex = c.getColumnIndexOrThrow(Favorites.ICON); 6670589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato 6680589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato while (c.moveToNext()) { 6690589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato long id = c.getLong(idIndex); 6700589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato byte[] data = c.getBlob(iconIndex); 6710589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato try { 6720589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato Bitmap bitmap = Utilities.resampleIconBitmap( 6730589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato BitmapFactory.decodeByteArray(data, 0, data.length), 6740589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato mContext); 6750589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato if (bitmap != null) { 6760589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato update.bindLong(1, id); 6770589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato data = ItemInfo.flattenBitmap(bitmap); 6780589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato if (data != null) { 6790589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato update.bindBlob(2, data); 6800589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato update.execute(); 6810589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato } 6820589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato bitmap.recycle(); 6830589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato } 6840589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato } catch (Exception e) { 6850589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato if (!logged) { 6860589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato Log.e(TAG, "Failed normalizing icon " + id, e); 6870589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato } else { 6880589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato Log.e(TAG, "Also failed normalizing icon " + id); 6890589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato } 6900589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato logged = true; 6910589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato } 6920589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato } 6933a928e46bdea32160c6cbecacdb2160389943a64Bjorn Bringert db.setTransactionSuccessful(); 6940589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato } catch (SQLException ex) { 6950589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato Log.w(TAG, "Problem while allocating appWidgetIds for existing widgets", ex); 6960589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato } finally { 6970589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato db.endTransaction(); 6989690b396d5f24a31ce8ffd9739f1f5d03a69bdceJoe Onorato if (update != null) { 6999690b396d5f24a31ce8ffd9739f1f5d03a69bdceJoe Onorato update.close(); 7009690b396d5f24a31ce8ffd9739f1f5d03a69bdceJoe Onorato } 7010589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato if (c != null) { 7020589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato c.close(); 7030589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato } 7040589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato } 705a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka } 706a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka 707a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka // Generates a new ID to use for an object in your database. This method should be only 708a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka // called from the main UI thread. As an exception, we do call it when we call the 709a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka // constructor from the worker thread; however, this doesn't extend until after the 710a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka // constructor is called, and we only pass a reference to LauncherProvider to LauncherApp 711a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka // after that point 712a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka public long generateNewId() { 713a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka if (mMaxId < 0) { 714a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka throw new RuntimeException("Error: max id was not initialized"); 715a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka } 716a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka mMaxId += 1; 717a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka return mMaxId; 718a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka } 719a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka 720a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka private long initializeMaxId(SQLiteDatabase db) { 721a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka Cursor c = db.rawQuery("SELECT MAX(_id) FROM favorites", null); 722a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka 723a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka // get the result 724a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka final int maxIdIndex = 0; 725a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka long id = -1; 726a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka if (c != null && c.moveToNext()) { 727a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka id = c.getLong(maxIdIndex); 728a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka } 7295130e401a005fcf6afba6e8e72a628fc45f9a287Michael Jurka if (c != null) { 7305130e401a005fcf6afba6e8e72a628fc45f9a287Michael Jurka c.close(); 7315130e401a005fcf6afba6e8e72a628fc45f9a287Michael Jurka } 732a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka 733a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka if (id == -1) { 734a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka throw new RuntimeException("Error: could not query max id"); 735a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka } 736a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka 737a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka return id; 7380589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato } 7390589f0f66ce498512c6ee47482c649d88294c9d0Joe Onorato 74031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project /** 7417376faefbbcbe30cc4e3f706ab95c254a4707d98The Android Open Source Project * Upgrade existing clock and photo frame widgets into their new widget 74293c45765cc5f4dbc0f1742a70854845f876c7ddcBjorn Bringert * equivalents. 74331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 74431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project private void convertWidgets(SQLiteDatabase db) { 7453425134204ad9dab032821016df40d4efda92f1aBjorn Bringert final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mContext); 74631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final int[] bindSources = new int[] { 74731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project Favorites.ITEM_TYPE_WIDGET_CLOCK, 74831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project Favorites.ITEM_TYPE_WIDGET_PHOTO_FRAME, 7497984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert Favorites.ITEM_TYPE_WIDGET_SEARCH, 75031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project }; 7517984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert 75231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final String selectWhere = buildOrWhereString(Favorites.ITEM_TYPE, bindSources); 753c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann 75431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project Cursor c = null; 755c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann 75631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project db.beginTransaction(); 75731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project try { 75831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project // Select and iterate through each matching widget 7597984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert c = db.query(TABLE_FAVORITES, new String[] { Favorites._ID, Favorites.ITEM_TYPE }, 76031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project selectWhere, null, null, null, null); 761c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann 762a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato if (LOGD) Log.d(TAG, "found upgrade cursor count=" + c.getCount()); 763c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann 76431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project final ContentValues values = new ContentValues(); 76531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project while (c != null && c.moveToNext()) { 76631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project long favoriteId = c.getLong(0); 7677984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert int favoriteType = c.getInt(1); 7687984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert 7697376faefbbcbe30cc4e3f706ab95c254a4707d98The Android Open Source Project // Allocate and update database with new appWidgetId 77031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project try { 7717376faefbbcbe30cc4e3f706ab95c254a4707d98The Android Open Source Project int appWidgetId = mAppWidgetHost.allocateAppWidgetId(); 772c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann 773a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato if (LOGD) { 774a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato Log.d(TAG, "allocated appWidgetId=" + appWidgetId 775a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato + " for favoriteId=" + favoriteId); 776a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato } 77731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project values.clear(); 7787984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_APPWIDGET); 7797984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert values.put(Favorites.APPWIDGET_ID, appWidgetId); 7807984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert 78131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project // Original widgets might not have valid spans when upgrading 7827984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert if (favoriteType == Favorites.ITEM_TYPE_WIDGET_SEARCH) { 7837984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert values.put(LauncherSettings.Favorites.SPANX, 4); 7847984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert values.put(LauncherSettings.Favorites.SPANY, 1); 7857984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert } else { 7867984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert values.put(LauncherSettings.Favorites.SPANX, 2); 7877984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert values.put(LauncherSettings.Favorites.SPANY, 2); 7887984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert } 78931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 79031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project String updateWhere = Favorites._ID + "=" + favoriteId; 79131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project db.update(TABLE_FAVORITES, values, updateWhere, null); 7923425134204ad9dab032821016df40d4efda92f1aBjorn Bringert 7933425134204ad9dab032821016df40d4efda92f1aBjorn Bringert if (favoriteType == Favorites.ITEM_TYPE_WIDGET_CLOCK) { 7948b805b17158886035b38261eb611d8641701ae43Michael Jurka // TODO: check return value 7958b805b17158886035b38261eb611d8641701ae43Michael Jurka appWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId, 7963425134204ad9dab032821016df40d4efda92f1aBjorn Bringert new ComponentName("com.android.alarmclock", 7973425134204ad9dab032821016df40d4efda92f1aBjorn Bringert "com.android.alarmclock.AnalogAppWidgetProvider")); 7983425134204ad9dab032821016df40d4efda92f1aBjorn Bringert } else if (favoriteType == Favorites.ITEM_TYPE_WIDGET_PHOTO_FRAME) { 7998b805b17158886035b38261eb611d8641701ae43Michael Jurka // TODO: check return value 8008b805b17158886035b38261eb611d8641701ae43Michael Jurka appWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId, 8013425134204ad9dab032821016df40d4efda92f1aBjorn Bringert new ComponentName("com.android.camera", 8023425134204ad9dab032821016df40d4efda92f1aBjorn Bringert "com.android.camera.PhotoAppWidgetProvider")); 8033425134204ad9dab032821016df40d4efda92f1aBjorn Bringert } else if (favoriteType == Favorites.ITEM_TYPE_WIDGET_SEARCH) { 8048b805b17158886035b38261eb611d8641701ae43Michael Jurka // TODO: check return value 8058b805b17158886035b38261eb611d8641701ae43Michael Jurka appWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId, 806cd8fec02810ac2d7ca97c4cbb41e37dace832ecbBjorn Bringert getSearchWidgetProvider()); 8073425134204ad9dab032821016df40d4efda92f1aBjorn Bringert } 80831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } catch (RuntimeException ex) { 809a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato Log.e(TAG, "Problem allocating appWidgetId", ex); 81031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 81131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 812c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann 81331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project db.setTransactionSuccessful(); 81431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } catch (SQLException ex) { 815a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato Log.w(TAG, "Problem while allocating appWidgetIds for existing widgets", ex); 81631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } finally { 81731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project db.endTransaction(); 81831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (c != null) { 81931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project c.close(); 82031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 82131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 82231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 82331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 8248b805b17158886035b38261eb611d8641701ae43Michael Jurka private static final void beginDocument(XmlPullParser parser, String firstElementName) 8258b805b17158886035b38261eb611d8641701ae43Michael Jurka throws XmlPullParserException, IOException { 8268b805b17158886035b38261eb611d8641701ae43Michael Jurka int type; 8279bc8eba3338455c5d915055e8ba044981c512dfaMichael Jurka while ((type = parser.next()) != XmlPullParser.START_TAG 8289bc8eba3338455c5d915055e8ba044981c512dfaMichael Jurka && type != XmlPullParser.END_DOCUMENT) { 8298b805b17158886035b38261eb611d8641701ae43Michael Jurka ; 8308b805b17158886035b38261eb611d8641701ae43Michael Jurka } 8318b805b17158886035b38261eb611d8641701ae43Michael Jurka 8329bc8eba3338455c5d915055e8ba044981c512dfaMichael Jurka if (type != XmlPullParser.START_TAG) { 8338b805b17158886035b38261eb611d8641701ae43Michael Jurka throw new XmlPullParserException("No start tag found"); 8348b805b17158886035b38261eb611d8641701ae43Michael Jurka } 8358b805b17158886035b38261eb611d8641701ae43Michael Jurka 8368b805b17158886035b38261eb611d8641701ae43Michael Jurka if (!parser.getName().equals(firstElementName)) { 8378b805b17158886035b38261eb611d8641701ae43Michael Jurka throw new XmlPullParserException("Unexpected start tag: found " + parser.getName() + 8388b805b17158886035b38261eb611d8641701ae43Michael Jurka ", expected " + firstElementName); 8398b805b17158886035b38261eb611d8641701ae43Michael Jurka } 8408b805b17158886035b38261eb611d8641701ae43Michael Jurka } 8418b805b17158886035b38261eb611d8641701ae43Michael Jurka 84231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project /** 84331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Loads the default set of favorite packages from an xml file. 84431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * 84531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * @param db The database to write the values into 8463d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung * @param filterContainerId The specific container id of items to load 84731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 8486d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung private int loadFavorites(SQLiteDatabase db, int workspaceResourceId) { 84931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project Intent intent = new Intent(Intent.ACTION_MAIN, null); 85031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project intent.addCategory(Intent.CATEGORY_LAUNCHER); 85131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project ContentValues values = new ContentValues(); 85231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 85331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project PackageManager packageManager = mContext.getPackageManager(); 8540dca1ec41479a74f8da080224fa0c7eacab674d6Andrew Flynn int allAppsButtonRank = 8550dca1ec41479a74f8da080224fa0c7eacab674d6Andrew Flynn mContext.getResources().getInteger(R.integer.hotseat_all_apps_index); 85631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project int i = 0; 85731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project try { 8586d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung XmlResourceParser parser = mContext.getResources().getXml(workspaceResourceId); 859f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project AttributeSet attrs = Xml.asAttributeSet(parser); 8608b805b17158886035b38261eb611d8641701ae43Michael Jurka beginDocument(parser, TAG_FAVORITES); 86131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 862f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project final int depth = parser.getDepth(); 86331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 864f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project int type; 865f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project while (((type = parser.next()) != XmlPullParser.END_TAG || 866f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) { 867f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project 868f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project if (type != XmlPullParser.START_TAG) { 869f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project continue; 87031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 87131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 872f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project boolean added = false; 873f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project final String name = parser.getName(); 874f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project 875f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.Favorite); 876f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project 8773d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung long container = LauncherSettings.Favorites.CONTAINER_DESKTOP; 8783d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung if (a.hasValue(R.styleable.Favorite_container)) { 8793d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung container = Long.valueOf(a.getString(R.styleable.Favorite_container)); 8803d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung } 8813d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung 8826d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung String screen = a.getString(R.styleable.Favorite_screen); 8836d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung String x = a.getString(R.styleable.Favorite_x); 8846d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung String y = a.getString(R.styleable.Favorite_y); 885228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen 8866d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung // If we are adding to the hotseat, the screen is used as the position in the 8876d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung // hotseat. This screen can't be at position 0 because AllApps is in the 8886d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung // zeroth position. 8890dca1ec41479a74f8da080224fa0c7eacab674d6Andrew Flynn if (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT 8900dca1ec41479a74f8da080224fa0c7eacab674d6Andrew Flynn && Integer.valueOf(screen) == allAppsButtonRank) { 8916d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung throw new RuntimeException("Invalid screen position for hotseat item"); 8926d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung } 893228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen 8946d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung values.clear(); 8956d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung values.put(LauncherSettings.Favorites.CONTAINER, container); 8966d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung values.put(LauncherSettings.Favorites.SCREEN, screen); 8976d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung values.put(LauncherSettings.Favorites.CELLX, x); 8986d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung values.put(LauncherSettings.Favorites.CELLY, y); 8996d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung 9006d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung if (TAG_FAVORITE.equals(name)) { 9016d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung long id = addAppShortcut(db, values, a, packageManager, intent); 9026d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung added = id >= 0; 9036d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung } else if (TAG_SEARCH.equals(name)) { 9046d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung added = addSearchWidget(db, values); 9056d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung } else if (TAG_CLOCK.equals(name)) { 9066d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung added = addClockWidget(db, values); 9076d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung } else if (TAG_APPWIDGET.equals(name)) { 908b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung added = addAppWidget(parser, attrs, type, db, values, a, packageManager); 9096d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung } else if (TAG_SHORTCUT.equals(name)) { 9106d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung long id = addUriShortcut(db, values, a); 9116d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung added = id >= 0; 9126d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung } else if (TAG_FOLDER.equals(name)) { 9136d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung String title; 9146d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung int titleResId = a.getResourceId(R.styleable.Favorite_title, -1); 9156d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung if (titleResId != -1) { 9166d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung title = mContext.getResources().getString(titleResId); 9176d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung } else { 9186d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung title = mContext.getResources().getString(R.string.folder_name); 9196d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung } 9206d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung values.put(LauncherSettings.Favorites.TITLE, title); 9216d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung long folderId = addFolder(db, values); 9226d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung added = folderId >= 0; 923228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen 9246d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung ArrayList<Long> folderItems = new ArrayList<Long>(); 9256d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung 9266d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung int folderDepth = parser.getDepth(); 9276d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung while ((type = parser.next()) != XmlPullParser.END_TAG || 9286d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung parser.getDepth() > folderDepth) { 9296d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung if (type != XmlPullParser.START_TAG) { 9306d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung continue; 931228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen } 9326d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung final String folder_item_name = parser.getName(); 9336d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung 9346d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung TypedArray ar = mContext.obtainStyledAttributes(attrs, 9356d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung R.styleable.Favorite); 9366d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung values.clear(); 9376d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung values.put(LauncherSettings.Favorites.CONTAINER, folderId); 9386d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung 9396d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung if (TAG_FAVORITE.equals(folder_item_name) && folderId >= 0) { 9406d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung long id = 9416d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung addAppShortcut(db, values, ar, packageManager, intent); 9426d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung if (id >= 0) { 9436d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung folderItems.add(id); 9446d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung } 9456d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung } else if (TAG_SHORTCUT.equals(folder_item_name) && folderId >= 0) { 9466d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung long id = addUriShortcut(db, values, ar); 9476d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung if (id >= 0) { 9486d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung folderItems.add(id); 949228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen } 9506d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung } else { 9516d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung throw new RuntimeException("Folders can " + 9526d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung "contain only shortcuts"); 9536d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung } 9546d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung ar.recycle(); 9556d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung } 9566d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung // We can only have folders with >= 2 items, so we need to remove the 9576d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung // folder and clean up if less than 2 items were included, or some 9586d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung // failed to add, and less than 2 were actually added 9596d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung if (folderItems.size() < 2 && folderId >= 0) { 9606d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung // We just delete the folder and any items that made it 9616d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung deleteId(db, folderId); 9626d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung if (folderItems.size() > 0) { 9636d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung deleteId(db, folderItems.get(0)); 964228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen } 9656d09268cdef87be5686e541ba25148c7d72e0d59Winson Chung added = false; 9663d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung } 96731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 968f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project if (added) i++; 969f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project a.recycle(); 97031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 97131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } catch (XmlPullParserException e) { 972a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato Log.w(TAG, "Got exception parsing favorites.", e); 97331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } catch (IOException e) { 974a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato Log.w(TAG, "Got exception parsing favorites.", e); 9753d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung } catch (RuntimeException e) { 9763d503fbd9468fb2b9fa645f4f7b91e11229edbfaWinson Chung Log.w(TAG, "Got exception parsing favorites.", e); 97731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 978f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project 979f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project return i; 980f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project } 981f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project 982228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen private long addAppShortcut(SQLiteDatabase db, ContentValues values, TypedArray a, 983f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project PackageManager packageManager, Intent intent) { 984228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen long id = -1; 985f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project ActivityInfo info; 986f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project String packageName = a.getString(R.styleable.Favorite_packageName); 987f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project String className = a.getString(R.styleable.Favorite_className); 988f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project try { 989693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy ComponentName cn; 990693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy try { 991693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy cn = new ComponentName(packageName, className); 992693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy info = packageManager.getActivityInfo(cn, 0); 993693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy } catch (PackageManager.NameNotFoundException nnfe) { 994693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy String[] packages = packageManager.currentToCanonicalPackageNames( 995693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy new String[] { packageName }); 996693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy cn = new ComponentName(packages[0], className); 997693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy info = packageManager.getActivityInfo(cn, 0); 998693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy } 999228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen id = generateNewId(); 1000f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project intent.setComponent(cn); 1001693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | 1002693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 10031ce1a24cba4dc41bccfeab6fccb2f3355423841aRomain Guy values.put(Favorites.INTENT, intent.toUri(0)); 1004f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project values.put(Favorites.TITLE, info.loadLabel(packageManager).toString()); 1005f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_APPLICATION); 1006f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project values.put(Favorites.SPANX, 1); 1007f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project values.put(Favorites.SPANY, 1); 1008a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka values.put(Favorites._ID, generateNewId()); 1009228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values) < 0) { 1010228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen return -1; 1011228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen } 1012f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project } catch (PackageManager.NameNotFoundException e) { 1013a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato Log.w(TAG, "Unable to add favorite: " + packageName + 1014f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project "/" + className, e); 1015f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project } 1016228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen return id; 1017228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen } 1018228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen 1019228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen private long addFolder(SQLiteDatabase db, ContentValues values) { 1020228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_FOLDER); 1021228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen values.put(Favorites.SPANX, 1); 1022228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen values.put(Favorites.SPANY, 1); 1023228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen long id = generateNewId(); 1024228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen values.put(Favorites._ID, id); 1025228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values) <= 0) { 1026228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen return -1; 1027228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen } else { 1028228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen return id; 1029228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen } 1030f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project } 1031f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project 1032cd8fec02810ac2d7ca97c4cbb41e37dace832ecbBjorn Bringert private ComponentName getSearchWidgetProvider() { 1033cd8fec02810ac2d7ca97c4cbb41e37dace832ecbBjorn Bringert SearchManager searchManager = 1034cd8fec02810ac2d7ca97c4cbb41e37dace832ecbBjorn Bringert (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE); 1035cd8fec02810ac2d7ca97c4cbb41e37dace832ecbBjorn Bringert ComponentName searchComponent = searchManager.getGlobalSearchActivity(); 1036cd8fec02810ac2d7ca97c4cbb41e37dace832ecbBjorn Bringert if (searchComponent == null) return null; 1037cd8fec02810ac2d7ca97c4cbb41e37dace832ecbBjorn Bringert return getProviderInPackage(searchComponent.getPackageName()); 1038cd8fec02810ac2d7ca97c4cbb41e37dace832ecbBjorn Bringert } 1039cd8fec02810ac2d7ca97c4cbb41e37dace832ecbBjorn Bringert 1040cd8fec02810ac2d7ca97c4cbb41e37dace832ecbBjorn Bringert /** 1041cd8fec02810ac2d7ca97c4cbb41e37dace832ecbBjorn Bringert * Gets an appwidget provider from the given package. If the package contains more than 1042cd8fec02810ac2d7ca97c4cbb41e37dace832ecbBjorn Bringert * one appwidget provider, an arbitrary one is returned. 1043cd8fec02810ac2d7ca97c4cbb41e37dace832ecbBjorn Bringert */ 1044cd8fec02810ac2d7ca97c4cbb41e37dace832ecbBjorn Bringert private ComponentName getProviderInPackage(String packageName) { 1045cd8fec02810ac2d7ca97c4cbb41e37dace832ecbBjorn Bringert AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mContext); 1046cd8fec02810ac2d7ca97c4cbb41e37dace832ecbBjorn Bringert List<AppWidgetProviderInfo> providers = appWidgetManager.getInstalledProviders(); 1047cd8fec02810ac2d7ca97c4cbb41e37dace832ecbBjorn Bringert if (providers == null) return null; 1048cd8fec02810ac2d7ca97c4cbb41e37dace832ecbBjorn Bringert final int providerCount = providers.size(); 1049cd8fec02810ac2d7ca97c4cbb41e37dace832ecbBjorn Bringert for (int i = 0; i < providerCount; i++) { 1050cd8fec02810ac2d7ca97c4cbb41e37dace832ecbBjorn Bringert ComponentName provider = providers.get(i).provider; 1051cd8fec02810ac2d7ca97c4cbb41e37dace832ecbBjorn Bringert if (provider != null && provider.getPackageName().equals(packageName)) { 1052cd8fec02810ac2d7ca97c4cbb41e37dace832ecbBjorn Bringert return provider; 1053cd8fec02810ac2d7ca97c4cbb41e37dace832ecbBjorn Bringert } 1054cd8fec02810ac2d7ca97c4cbb41e37dace832ecbBjorn Bringert } 1055cd8fec02810ac2d7ca97c4cbb41e37dace832ecbBjorn Bringert return null; 1056cd8fec02810ac2d7ca97c4cbb41e37dace832ecbBjorn Bringert } 1057cd8fec02810ac2d7ca97c4cbb41e37dace832ecbBjorn Bringert 1058f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project private boolean addSearchWidget(SQLiteDatabase db, ContentValues values) { 1059cd8fec02810ac2d7ca97c4cbb41e37dace832ecbBjorn Bringert ComponentName cn = getSearchWidgetProvider(); 1060b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung return addAppWidget(db, values, cn, 4, 1, null); 1061f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project } 1062f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project 1063f96811cdf564469a7a654a0c876288c9fd14f35eThe Android Open Source Project private boolean addClockWidget(SQLiteDatabase db, ContentValues values) { 10643425134204ad9dab032821016df40d4efda92f1aBjorn Bringert ComponentName cn = new ComponentName("com.android.alarmclock", 10653425134204ad9dab032821016df40d4efda92f1aBjorn Bringert "com.android.alarmclock.AnalogAppWidgetProvider"); 1066b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung return addAppWidget(db, values, cn, 2, 2, null); 106731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 1068228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen 1069b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung private boolean addAppWidget(XmlResourceParser parser, AttributeSet attrs, int type, 1070b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung SQLiteDatabase db, ContentValues values, TypedArray a, 1071b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung PackageManager packageManager) throws XmlPullParserException, IOException { 1072693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy 1073b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron String packageName = a.getString(R.styleable.Favorite_packageName); 1074b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron String className = a.getString(R.styleable.Favorite_className); 1075b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron 1076b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron if (packageName == null || className == null) { 1077b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron return false; 1078b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron } 1079693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy 1080693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy boolean hasPackage = true; 1081b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron ComponentName cn = new ComponentName(packageName, className); 1082693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy try { 1083693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy packageManager.getReceiverInfo(cn, 0); 1084693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy } catch (Exception e) { 1085693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy String[] packages = packageManager.currentToCanonicalPackageNames( 1086693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy new String[] { packageName }); 1087693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy cn = new ComponentName(packages[0], className); 1088693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy try { 1089693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy packageManager.getReceiverInfo(cn, 0); 1090693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy } catch (Exception e1) { 1091693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy hasPackage = false; 1092693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy } 1093693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy } 1094693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy 1095693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy if (hasPackage) { 1096693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy int spanX = a.getInt(R.styleable.Favorite_spanX, 0); 1097693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy int spanY = a.getInt(R.styleable.Favorite_spanY, 0); 1098b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung 1099b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung // Read the extras 1100b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung Bundle extras = new Bundle(); 1101b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung int widgetDepth = parser.getDepth(); 1102b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung while ((type = parser.next()) != XmlPullParser.END_TAG || 1103b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung parser.getDepth() > widgetDepth) { 1104b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung if (type != XmlPullParser.START_TAG) { 1105b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung continue; 1106b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung } 1107b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung 1108b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung TypedArray ar = mContext.obtainStyledAttributes(attrs, R.styleable.Extra); 1109b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung if (TAG_EXTRA.equals(parser.getName())) { 1110b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung String key = ar.getString(R.styleable.Extra_key); 1111b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung String value = ar.getString(R.styleable.Extra_value); 1112b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung if (key != null && value != null) { 1113b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung extras.putString(key, value); 1114b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung } else { 1115b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung throw new RuntimeException("Widget extras must have a key and value"); 1116b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung } 1117b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung } else { 1118b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung throw new RuntimeException("Widgets can contain only extras"); 1119b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung } 1120b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung ar.recycle(); 1121b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung } 1122b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung 1123b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung return addAppWidget(db, values, cn, spanX, spanY, extras); 1124693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy } 1125c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann 1126693599f27be9f3f2d59d3205283133b5b504d3c8Romain Guy return false; 11277984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert } 11287984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert 11297984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert private boolean addAppWidget(SQLiteDatabase db, ContentValues values, ComponentName cn, 1130b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung int spanX, int spanY, Bundle extras) { 1131b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron boolean allocatedAppWidgets = false; 1132b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mContext); 1133b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron 1134b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron try { 1135b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron int appWidgetId = mAppWidgetHost.allocateAppWidgetId(); 1136c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann 1137b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_APPWIDGET); 11387984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert values.put(Favorites.SPANX, spanX); 11397984c9496bcaeca23ee7fdecc4d4f1bb2467e0f2Bjorn Bringert values.put(Favorites.SPANY, spanY); 1140b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron values.put(Favorites.APPWIDGET_ID, appWidgetId); 1141a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka values.put(Favorites._ID, generateNewId()); 1142a8c760d395e1d2a78522427738302fbca3a72453Michael Jurka dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values); 1143b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron 1144b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron allocatedAppWidgets = true; 1145c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann 11468b805b17158886035b38261eb611d8641701ae43Michael Jurka // TODO: need to check return value 11478b805b17158886035b38261eb611d8641701ae43Michael Jurka appWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId, cn); 1148b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung 1149b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung // Send a broadcast to configure the widget 1150b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung if (extras != null && !extras.isEmpty()) { 1151b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung Intent intent = new Intent(ACTION_APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE); 1152b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung intent.setComponent(cn); 1153b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung intent.putExtras(extras); 1154b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); 1155b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung mContext.sendBroadcast(intent); 1156b3302aee121b46f97aa7afc7e5e2f58f3309aa9bWinson Chung } 1157b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron } catch (RuntimeException ex) { 1158a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato Log.e(TAG, "Problem allocating appWidgetId", ex); 1159b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron } 1160c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann 1161b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron return allocatedAppWidgets; 1162b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron } 1163228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen 1164228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen private long addUriShortcut(SQLiteDatabase db, ContentValues values, 1165b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron TypedArray a) { 1166b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron Resources r = mContext.getResources(); 1167b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron 1168b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron final int iconResId = a.getResourceId(R.styleable.Favorite_icon, 0); 1169b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron final int titleResId = a.getResourceId(R.styleable.Favorite_title, 0); 1170b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron 11717eb9e5e9257635cee5609ed633eb575fda93dd5aRomain Guy Intent intent; 1172b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron String uri = null; 1173b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron try { 1174b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron uri = a.getString(R.styleable.Favorite_uri); 1175b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron intent = Intent.parseUri(uri, 0); 1176b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron } catch (URISyntaxException e) { 1177a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato Log.w(TAG, "Shortcut has malformed uri: " + uri); 1178228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen return -1; // Oh well 1179b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron } 1180b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron 1181b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron if (iconResId == 0 || titleResId == 0) { 1182a30ce8e6b25e41f392a41fd4d0d3e0a424a84dadJoe Onorato Log.w(TAG, "Shortcut is missing title or icon resource ID"); 1183228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen return -1; 1184b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron } 1185b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron 1186228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen long id = generateNewId(); 1187b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1188b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron values.put(Favorites.INTENT, intent.toUri(0)); 1189b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron values.put(Favorites.TITLE, r.getString(titleResId)); 1190b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron values.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_SHORTCUT); 1191b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron values.put(Favorites.SPANX, 1); 1192b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron values.put(Favorites.SPANY, 1); 1193b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron values.put(Favorites.ICON_TYPE, Favorites.ICON_TYPE_RESOURCE); 1194b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron values.put(Favorites.ICON_PACKAGE, mContext.getPackageName()); 1195b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron values.put(Favorites.ICON_RESOURCE, r.getResourceName(iconResId)); 1196228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen values.put(Favorites._ID, id); 1197b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron 1198228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, values) < 0) { 1199228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen return -1; 1200228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen } 1201228da5a24e5a680cfb7bec14a24d20b5cb595a34Adam Cohen return id; 1202b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron } 1203b87bd16c8e3f88a9ba78ed00c9f150b38dc39f33Mike Cleron } 1204c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann 120531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project /** 120631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * Build a query string that will match any row where the column matches 120731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project * anything in the values list. 120831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project */ 120931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project static String buildOrWhereString(String column, int[] values) { 121031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project StringBuilder selectWhere = new StringBuilder(); 121131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project for (int i = values.length - 1; i >= 0; i--) { 121231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project selectWhere.append(column).append("=").append(values[i]); 121331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (i > 0) { 121431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project selectWhere.append(" OR "); 121531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 121631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 121731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project return selectWhere.toString(); 121831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 121931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 122031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project static class SqlArguments { 122131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public final String table; 122231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public final String where; 122331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project public final String[] args; 122431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 122531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project SqlArguments(Uri url, String where, String[] args) { 122631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (url.getPathSegments().size() == 1) { 122731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project this.table = url.getPathSegments().get(0); 122831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project this.where = where; 122931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project this.args = args; 123031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } else if (url.getPathSegments().size() != 2) { 123131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project throw new IllegalArgumentException("Invalid URI: " + url); 123231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } else if (!TextUtils.isEmpty(where)) { 123331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project throw new UnsupportedOperationException("WHERE clause not supported: " + url); 123431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } else { 123531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project this.table = url.getPathSegments().get(0); 1236c3a804042844dc4733b4bd4b6ac03bf4b2b015b7Daniel Lehmann this.where = "_id=" + ContentUris.parseId(url); 123731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project this.args = null; 123831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 123931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 124031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project 124131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project SqlArguments(Uri url) { 124231dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project if (url.getPathSegments().size() == 1) { 124331dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project table = url.getPathSegments().get(0); 124431dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project where = null; 124531dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project args = null; 124631dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } else { 124731dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project throw new IllegalArgumentException("Invalid URI: " + url); 124831dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 124931dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 125031dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project } 125131dd503c6aa69018e694d91724d46db49ea09327The Android Open Source Project} 1252