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