diff options
Diffstat (limited to 'src/com/android/launcher/LauncherModel.java')
-rw-r--r-- | src/com/android/launcher/LauncherModel.java | 995 |
1 files changed, 995 insertions, 0 deletions
diff --git a/src/com/android/launcher/LauncherModel.java b/src/com/android/launcher/LauncherModel.java new file mode 100644 index 000000000..40b5402c0 --- /dev/null +++ b/src/com/android/launcher/LauncherModel.java @@ -0,0 +1,995 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher; + +import android.content.ComponentName; +import android.content.ContentResolver; +import android.content.ContentValues; +import android.content.Intent; +import android.content.Context; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.res.Resources; +import android.database.Cursor; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.Uri; +import android.util.Log; +import android.os.Process; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Comparator; +import java.lang.ref.WeakReference; +import java.text.Collator; +import java.net.URISyntaxException; + +/** + * Maintains in-memory state of the Launcher. It is expected that there should be only one + * LauncherModel object held in a static. Also provide APIs for updating the database state + * for the Launcher + */ +public class LauncherModel { + private static final int UI_NOTIFICATION_RATE = 4; + private static final int DEFAULT_APPLICATIONS_NUMBER = 42; + private static final long APPLICATION_NOT_RESPONDING_TIMEOUT = 5000; + + private final Collator sCollator = Collator.getInstance(); + + private boolean mApplicationsLoaded; + private boolean mDesktopItemsLoaded; + + private ArrayList<ItemInfo> mDesktopItems; + private ArrayList<LauncherGadgetInfo> mDesktopGadgets; + private HashMap<Long, FolderInfo> mFolders; + + private ArrayList<ApplicationInfo> mApplications; + private ApplicationsAdapter mApplicationsAdapter; + private ApplicationsLoader mApplicationsLoader; + private DesktopItemsLoader mDesktopItemsLoader; + private Thread mLoader; + private Thread mDesktopLoader; + + void abortLoaders() { + if (mApplicationsLoader != null && mApplicationsLoader.isRunning()) { + mApplicationsLoader.stop(); + mApplicationsLoaded = false; + } + if (mDesktopItemsLoader != null && mDesktopItemsLoader.isRunning()) { + mDesktopItemsLoader.stop(); + mDesktopItemsLoaded = false; + } + } + + /** + * Loads the list of installed applications in mApplications. + */ + void loadApplications(boolean isLaunching, Launcher launcher, boolean localeChanged) { + if (isLaunching && mApplicationsLoaded && !localeChanged) { + mApplicationsAdapter = new ApplicationsAdapter(launcher, mApplications); + return; + } + + if (mApplicationsAdapter == null || isLaunching || localeChanged) { + mApplicationsAdapter = new ApplicationsAdapter(launcher, + mApplications = new ArrayList<ApplicationInfo>(DEFAULT_APPLICATIONS_NUMBER)); + } + + if (mApplicationsLoader != null && mApplicationsLoader.isRunning()) { + mApplicationsLoader.stop(); + // Wait for the currently running thread to finish, this can take a little + // time but it should be well below the timeout limit + try { + mLoader.join(APPLICATION_NOT_RESPONDING_TIMEOUT); + } catch (InterruptedException e) { + // Empty + } + } + + mApplicationsLoaded = false; + + if (!isLaunching) { + startApplicationsLoader(launcher); + } + } + + private void startApplicationsLoader(Launcher launcher) { + mApplicationsLoader = new ApplicationsLoader(launcher); + mLoader = new Thread(mApplicationsLoader, "Applications Loader"); + mLoader.start(); + } + + private class ApplicationsLoader implements Runnable { + private final WeakReference<Launcher> mLauncher; + + private volatile boolean mStopped; + private volatile boolean mRunning; + + ApplicationsLoader(Launcher launcher) { + mLauncher = new WeakReference<Launcher>(launcher); + } + + void stop() { + mStopped = true; + } + + boolean isRunning() { + return mRunning; + } + + public void run() { + mRunning = true; + + android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); + + Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); + mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); + + final Launcher launcher = mLauncher.get(); + final PackageManager manager = launcher.getPackageManager(); + final List<ResolveInfo> apps = manager.queryIntentActivities(mainIntent, 0); + + if (apps != null && !mStopped) { + final int count = apps.size(); + final ApplicationsAdapter applicationList = mApplicationsAdapter; + + ChangeNotifier action = new ChangeNotifier(applicationList); + + for (int i = 0; i < count && !mStopped; i++) { + ApplicationInfo application = new ApplicationInfo(); + ResolveInfo info = apps.get(i); + + application.title = info.loadLabel(manager); + if (application.title == null) { + application.title = info.activityInfo.name; + } + application.setActivity(new ComponentName( + info.activityInfo.applicationInfo.packageName, + info.activityInfo.name), + Intent.FLAG_ACTIVITY_NEW_TASK | + Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); + application.icon = info.activityInfo.loadIcon(manager); + application.container = ItemInfo.NO_ID; + + action.add(application); + } + + action.sort(new Comparator<ApplicationInfo>() { + public final int compare(ApplicationInfo a, ApplicationInfo b) { + return sCollator.compare(a.title.toString(), b.title.toString()); + } + }); + + if (!mStopped) { + launcher.runOnUiThread(action); + } + } + + if (!mStopped) { + mApplicationsLoaded = true; + } + mRunning = false; + } + } + + private static class ChangeNotifier implements Runnable { + private final ApplicationsAdapter mApplicationList; + private ArrayList<ApplicationInfo> mBuffer; + + ChangeNotifier(ApplicationsAdapter applicationList) { + mApplicationList = applicationList; + mBuffer = new ArrayList<ApplicationInfo>(UI_NOTIFICATION_RATE); + } + + public void run() { + final ArrayList<ApplicationInfo> buffer = mBuffer; + final ApplicationsAdapter applicationList = mApplicationList; + final int count = buffer.size(); + + applicationList.setNotifyOnChange(false); + applicationList.clear(); + for (int i = 0; i < count; i++) { + applicationList.setNotifyOnChange(false); + applicationList.add(buffer.get(i)); + } + + applicationList.notifyDataSetChanged(); + buffer.clear(); + } + + void add(ApplicationInfo application) { + mBuffer.add(application); + } + + void sort(Comparator<ApplicationInfo> comparator) { + Collections.sort(mBuffer, comparator); + } + } + + boolean isDesktopLoaded() { + return mDesktopItems != null && mDesktopGadgets != null && mDesktopItemsLoaded; + } + + /** + * Loads all of the items on the desktop, in folders, or in the dock. + * These can be apps, shortcuts or widgets + */ + void loadUserItems(boolean isLaunching, Launcher launcher, boolean localeChanged, + boolean loadApplications) { + + if (isLaunching && isDesktopLoaded()) { + if (loadApplications) startApplicationsLoader(launcher); + // We have already loaded our data from the DB + launcher.onDesktopItemsLoaded(); + return; + } + + if (mDesktopItemsLoader != null && mDesktopItemsLoader.isRunning()) { + mDesktopItemsLoader.stop(); + // Wait for the currently running thread to finish, this can take a little + // time but it should be well below the timeout limit + try { + mDesktopLoader.join(APPLICATION_NOT_RESPONDING_TIMEOUT); + } catch (InterruptedException e) { + // Empty + } + } + + mDesktopItemsLoaded = false; + mDesktopItemsLoader = new DesktopItemsLoader(launcher, localeChanged, loadApplications); + mDesktopLoader = new Thread(mDesktopItemsLoader, "Desktop Items Loader"); + mDesktopLoader.start(); + } + + private static void updateShortcutLabels(ContentResolver resolver, PackageManager manager) { + final Cursor c = resolver.query(LauncherSettings.Favorites.CONTENT_URI, + new String[] { LauncherSettings.Favorites.ID, LauncherSettings.Favorites.TITLE, + LauncherSettings.Favorites.INTENT, LauncherSettings.Favorites.ITEM_TYPE }, + null, null, null); + + final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ID); + final int intentIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT); + final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE); + final int titleIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE); + + // boolean changed = false; + + try { + while (c.moveToNext()) { + try { + if (c.getInt(itemTypeIndex) != + LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) { + continue; + } + + final String intentUri = c.getString(intentIndex); + if (intentUri != null) { + final Intent shortcut = Intent.getIntent(intentUri); + if (Intent.ACTION_MAIN.equals(shortcut.getAction())) { + final ComponentName name = shortcut.getComponent(); + if (name != null) { + final ActivityInfo activityInfo = manager.getActivityInfo(name, 0); + final String title = c.getString(titleIndex); + String label = getLabel(manager, activityInfo); + + if (title == null || !title.equals(label)) { + final ContentValues values = new ContentValues(); + values.put(LauncherSettings.Favorites.TITLE, label); + + resolver.update(LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION, + values, "_id=?", + new String[] { String.valueOf(c.getLong(idIndex)) }); + + // changed = true; + } + } + } + } + } catch (URISyntaxException e) { + // Ignore + } catch (PackageManager.NameNotFoundException e) { + // Ignore + } + } + } finally { + c.close(); + } + + // if (changed) resolver.notifyChange(Settings.Favorites.CONTENT_URI, null); + } + + private static String getLabel(PackageManager manager, ActivityInfo activityInfo) { + String label = activityInfo.loadLabel(manager).toString(); + if (label == null) { + label = manager.getApplicationLabel(activityInfo.applicationInfo).toString(); + if (label == null) { + label = activityInfo.name; + } + } + return label; + } + + private class DesktopItemsLoader implements Runnable { + private volatile boolean mStopped; + private volatile boolean mRunning; + + private final WeakReference<Launcher> mLauncher; + private final boolean mLocaleChanged; + private final boolean mLoadApplications; + + DesktopItemsLoader(Launcher launcher, boolean localeChanged, boolean loadApplications) { + mLoadApplications = loadApplications; + mLauncher = new WeakReference<Launcher>(launcher); + mLocaleChanged = localeChanged; + } + + void stop() { + mStopped = true; + } + + boolean isRunning() { + return mRunning; + } + + public void run() { + mRunning = true; + + final Launcher launcher = mLauncher.get(); + final ContentResolver contentResolver = launcher.getContentResolver(); + final PackageManager manager = launcher.getPackageManager(); + + if (mLocaleChanged) { + updateShortcutLabels(contentResolver, manager); + } + + mDesktopItems = new ArrayList<ItemInfo>(); + mDesktopGadgets = new ArrayList<LauncherGadgetInfo>(); + mFolders = new HashMap<Long, FolderInfo>(); + + final ArrayList<ItemInfo> desktopItems = mDesktopItems; + final ArrayList<LauncherGadgetInfo> desktopGadgets = mDesktopGadgets; + + final Cursor c = contentResolver.query( + LauncherSettings.Favorites.CONTENT_URI, null, null, null, null); + + try { + final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ID); + final int intentIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT); + final int titleIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE); + final int iconTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_TYPE); + final int iconIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON); + final int iconPackageIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_PACKAGE); + final int iconResourceIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_RESOURCE); + final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER); + final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE); + final int gadgetIdIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.GADGET_ID); + final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN); + final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX); + final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY); + final int spanXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANX); + final int spanYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANY); + final int uriIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.URI); + final int displayModeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.DISPLAY_MODE); + + ApplicationInfo info; + String intentDescription; + Widget widgetInfo; + LauncherGadgetInfo gadgetInfo; + int container; + long id; + Intent intent; + + final HashMap<Long, FolderInfo> folders = mFolders; + + while (!mStopped && c.moveToNext()) { + try { + int itemType = c.getInt(itemTypeIndex); + + switch (itemType) { + case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: + case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT: + intentDescription = c.getString(intentIndex); + try { + intent = Intent.getIntent(intentDescription); + } catch (java.net.URISyntaxException e) { + continue; + } + + if (itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) { + info = getApplicationInfo(manager, intent); + } else { + info = getApplicationInfoShortcut(c, launcher, iconTypeIndex, + iconPackageIndex, iconResourceIndex, iconIndex); + } + + if (info == null) { + info = new ApplicationInfo(); + info.icon = manager.getDefaultActivityIcon(); + } + + if (info != null) { + info.title = c.getString(titleIndex); + info.intent = intent; + + info.id = c.getLong(idIndex); + container = c.getInt(containerIndex); + info.container = container; + info.screen = c.getInt(screenIndex); + info.cellX = c.getInt(cellXIndex); + info.cellY = c.getInt(cellYIndex); + + switch (container) { + case LauncherSettings.Favorites.CONTAINER_DESKTOP: + desktopItems.add(info); + break; + default: + // Item is in a user folder + UserFolderInfo folderInfo = + findOrMakeUserFolder(folders, container); + folderInfo.add(info); + break; + } + } + break; + case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER: + + id = c.getLong(idIndex); + UserFolderInfo folderInfo = findOrMakeUserFolder(folders, id); + + folderInfo.title = c.getString(titleIndex); + + folderInfo.id = id; + container = c.getInt(containerIndex); + folderInfo.container = container; + folderInfo.screen = c.getInt(screenIndex); + folderInfo.cellX = c.getInt(cellXIndex); + folderInfo.cellY = c.getInt(cellYIndex); + + switch (container) { + case LauncherSettings.Favorites.CONTAINER_DESKTOP: + desktopItems.add(folderInfo); + break; + } + break; + case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER: + + id = c.getLong(idIndex); + LiveFolderInfo liveFolderInfo = findOrMakeLiveFolder(folders, id); + + intentDescription = c.getString(intentIndex); + intent = null; + if (intentDescription != null) { + try { + intent = Intent.getIntent(intentDescription); + } catch (java.net.URISyntaxException e) { + // Ignore, a live folder might not have a base intent + } + } + + liveFolderInfo.title = c.getString(titleIndex); + liveFolderInfo.id = id; + container = c.getInt(containerIndex); + liveFolderInfo.container = container; + liveFolderInfo.screen = c.getInt(screenIndex); + liveFolderInfo.cellX = c.getInt(cellXIndex); + liveFolderInfo.cellY = c.getInt(cellYIndex); + liveFolderInfo.uri = Uri.parse(c.getString(uriIndex)); + liveFolderInfo.baseIntent = intent; + liveFolderInfo.displayMode = c.getInt(displayModeIndex); + + loadLiveFolderIcon(launcher, c, iconTypeIndex, iconPackageIndex, + iconResourceIndex, liveFolderInfo); + + switch (container) { + case LauncherSettings.Favorites.CONTAINER_DESKTOP: + desktopItems.add(liveFolderInfo); + break; + } + break; + case LauncherSettings.Favorites.ITEM_TYPE_WIDGET_SEARCH: + widgetInfo = Widget.makeSearch(); + + container = c.getInt(containerIndex); + if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP) { + Log.e(Launcher.LOG_TAG, "Widget found where container " + + "!= CONTAINER_DESKTOP ignoring!"); + continue; + } + + widgetInfo.id = c.getLong(idIndex); + widgetInfo.screen = c.getInt(screenIndex); + widgetInfo.container = container; + widgetInfo.cellX = c.getInt(cellXIndex); + widgetInfo.cellY = c.getInt(cellYIndex); + + desktopItems.add(widgetInfo); + break; + case LauncherSettings.Favorites.ITEM_TYPE_GADGET: + // Read all Launcher-specific gadget details + int gadgetId = c.getInt(gadgetIdIndex); + gadgetInfo = new LauncherGadgetInfo(gadgetId); + gadgetInfo.id = c.getLong(idIndex); + gadgetInfo.screen = c.getInt(screenIndex); + gadgetInfo.cellX = c.getInt(cellXIndex); + gadgetInfo.cellY = c.getInt(cellYIndex); + gadgetInfo.spanX = c.getInt(spanXIndex); + gadgetInfo.spanY = c.getInt(spanYIndex); + + container = c.getInt(containerIndex); + if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP) { + Log.e(Launcher.LOG_TAG, "Gadget found where container " + + "!= CONTAINER_DESKTOP -- ignoring!"); + continue; + } + gadgetInfo.container = c.getInt(containerIndex); + + desktopGadgets.add(gadgetInfo); + break; + } + } catch (Exception e) { + Log.w(Launcher.LOG_TAG, "Desktop items loading interrupted:", e); + } + } + } finally { + c.close(); + } + + if (!mStopped) { + launcher.runOnUiThread(new Runnable() { + public void run() { + launcher.onDesktopItemsLoaded(); + } + }); + if (mLoadApplications) startApplicationsLoader(launcher); + } + + if (!mStopped) { + mDesktopItemsLoaded = true; + } + mRunning = false; + } + } + + private static void loadLiveFolderIcon(Launcher launcher, Cursor c, int iconTypeIndex, + int iconPackageIndex, int iconResourceIndex, LiveFolderInfo liveFolderInfo) { + + int iconType = c.getInt(iconTypeIndex); + switch (iconType) { + case LauncherSettings.Favorites.ICON_TYPE_RESOURCE: + String packageName = c.getString(iconPackageIndex); + String resourceName = c.getString(iconResourceIndex); + PackageManager packageManager = launcher.getPackageManager(); + try { + Resources resources = packageManager.getResourcesForApplication(packageName); + final int id = resources.getIdentifier(resourceName, null, null); + liveFolderInfo.icon = resources.getDrawable(id); + } catch (Exception e) { + liveFolderInfo.icon = + launcher.getResources().getDrawable(R.drawable.ic_launcher_folder); + } + liveFolderInfo.iconResource = new Intent.ShortcutIconResource(); + liveFolderInfo.iconResource.packageName = packageName; + liveFolderInfo.iconResource.resourceName = resourceName; + break; + default: + liveFolderInfo.icon = + launcher.getResources().getDrawable(R.drawable.ic_launcher_folder); + } + } + + /** + * Finds the user folder defined by the specified id. + * + * @param id The id of the folder to look for. + * + * @return A UserFolderInfo if the folder exists or null otherwise. + */ + FolderInfo findFolderById(long id) { + return mFolders.get(id); + } + + void addFolder(FolderInfo info) { + mFolders.put(info.id, info); + } + + /** + * Return an existing UserFolderInfo object if we have encountered this ID previously, or make a + * new one. + */ + private UserFolderInfo findOrMakeUserFolder(HashMap<Long, FolderInfo> folders, long id) { + // See if a placeholder was created for us already + FolderInfo folderInfo = folders.get(id); + if (folderInfo == null || !(folderInfo instanceof UserFolderInfo)) { + // No placeholder -- create a new instance + folderInfo = new UserFolderInfo(); + folders.put(id, folderInfo); + } + return (UserFolderInfo) folderInfo; + } + + /** + * Return an existing UserFolderInfo object if we have encountered this ID previously, or make a + * new one. + */ + private LiveFolderInfo findOrMakeLiveFolder(HashMap<Long, FolderInfo> folders, long id) { + // See if a placeholder was created for us already + FolderInfo folderInfo = folders.get(id); + if (folderInfo == null || !(folderInfo instanceof LiveFolderInfo)) { + // No placeholder -- create a new instance + folderInfo = new LiveFolderInfo(); + folders.put(id, folderInfo); + } + return (LiveFolderInfo) folderInfo; + } + + /** + * Remove the callback for the cached drawables or we leak the previous + * Home screen on orientation change. + */ + void unbind() { + mApplicationsAdapter = null; + unbindAppDrawables(mApplications); + unbindDrawables(mDesktopItems); + unbindGadgetHostViews(mDesktopGadgets); + } + + /** + * Remove the callback for the cached drawables or we leak the previous + * Home screen on orientation change. + */ + private void unbindDrawables(ArrayList<ItemInfo> desktopItems) { + if (desktopItems != null) { + final int count = desktopItems.size(); + for (int i = 0; i < count; i++) { + ItemInfo item = desktopItems.get(i); + switch (item.itemType) { + case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: + case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT: + ((ApplicationInfo)item).icon.setCallback(null); + break; + } + } + } + } + + /** + * Remove the callback for the cached drawables or we leak the previous + * Home screen on orientation change. + */ + private void unbindAppDrawables(ArrayList<ApplicationInfo> applications) { + if (applications != null) { + final int count = applications.size(); + for (int i = 0; i < count; i++) { + applications.get(i).icon.setCallback(null); + } + } + } + + /** + * Remove any {@link LauncherGadgetHostView} references in our gadgets. + */ + private void unbindGadgetHostViews(ArrayList<LauncherGadgetInfo> gadgets) { + if (gadgets != null) { + final int count = gadgets.size(); + for (int i = 0; i < count; i++) { + LauncherGadgetInfo launcherInfo = gadgets.get(i); + launcherInfo.hostView = null; + } + } + } + + /** + * @return The current list of applications + */ + public ArrayList<ApplicationInfo> getApplications() { + return mApplications; + } + + /** + * @return The current list of applications + */ + public ApplicationsAdapter getApplicationsAdapter() { + return mApplicationsAdapter; + } + + /** + * @return The current list of desktop items + */ + public ArrayList<ItemInfo> getDesktopItems() { + return mDesktopItems; + } + + /** + * @return The current list of desktop items + */ + public ArrayList<LauncherGadgetInfo> getDesktopGadgets() { + return mDesktopGadgets; + } + + /** + * Add an item to the desktop + * @param info + */ + public void addDesktopItem(ItemInfo info) { + // TODO: write to DB; also check that folder has been added to folders list + mDesktopItems.add(info); + } + + /** + * Remove an item from the desktop + * @param info + */ + public void removeDesktopItem(ItemInfo info) { + // TODO: write to DB; figure out if we should remove folder from folders list + mDesktopItems.remove(info); + } + + /** + * Add a gadget to the desktop + */ + public void addDesktopGadget(LauncherGadgetInfo info) { + mDesktopGadgets.add(info); + } + + /** + * Remove a gadget from the desktop + */ + public void removeDesktopGadget(LauncherGadgetInfo info) { + mDesktopGadgets.remove(info); + } + + /** + * Make an ApplicationInfo object for an application + */ + private static ApplicationInfo getApplicationInfo(PackageManager manager, Intent intent) { + final ResolveInfo resolveInfo = manager.resolveActivity(intent, 0); + + if (resolveInfo == null) { + return null; + } + + final ApplicationInfo info = new ApplicationInfo(); + final ActivityInfo activityInfo = resolveInfo.activityInfo; + info.icon = activityInfo.loadIcon(manager); + if (info.title == null || info.title.length() == 0) { + info.title = activityInfo.loadLabel(manager); + } + if (info.title == null) { + info.title = ""; + } + info.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION; + return info; + } + + /** + * Make an ApplicationInfo object for a sortcut + */ + private ApplicationInfo getApplicationInfoShortcut(Cursor c, Launcher launcher, + int iconTypeIndex, int iconPackageIndex, int iconResourceIndex, int iconIndex) { + + final ApplicationInfo info = new ApplicationInfo(); + info.itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT; + + int iconType = c.getInt(iconTypeIndex); + switch (iconType) { + case LauncherSettings.Favorites.ICON_TYPE_RESOURCE: + String packageName = c.getString(iconPackageIndex); + String resourceName = c.getString(iconResourceIndex); + PackageManager packageManager = launcher.getPackageManager(); + try { + Resources resources = packageManager.getResourcesForApplication(packageName); + final int id = resources.getIdentifier(resourceName, null, null); + info.icon = resources.getDrawable(id); + } catch (Exception e) { + info.icon = packageManager.getDefaultActivityIcon(); + } + info.iconResource = new Intent.ShortcutIconResource(); + info.iconResource.packageName = packageName; + info.iconResource.resourceName = resourceName; + info.customIcon = false; + break; + case LauncherSettings.Favorites.ICON_TYPE_BITMAP: + byte[] data = c.getBlob(iconIndex); + Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); + info.icon = new FastBitmapDrawable( + Utilities.createBitmapThumbnail(bitmap, launcher)); + info.filtered = true; + info.customIcon = true; + break; + default: + info.icon = launcher.getPackageManager().getDefaultActivityIcon(); + info.customIcon = false; + break; + } + return info; + } + + /** + * Remove an item from the in-memory represention of a user folder. Does not change the DB. + */ + void removeUserFolderItem(UserFolderInfo folder, ItemInfo info) { + //noinspection SuspiciousMethodCalls + folder.contents.remove(info); + } + + /** + * Removes a UserFolder from the in-memory list of folders. Does not change the DB. + * @param userFolderInfo + */ + void removeUserFolder(UserFolderInfo userFolderInfo) { + mFolders.remove(userFolderInfo.id); + } + + /** + * Adds an item to the DB if it was not created previously, or move it to a new + * <container, screen, cellX, cellY> + */ + static void addOrMoveItemInDatabase(Context context, ItemInfo item, long container, + int screen, int cellX, int cellY) { + if (item.container == ItemInfo.NO_ID) { + // From all apps + addItemToDatabase(context, item, container, screen, cellX, cellY, false); + } else { + // From somewhere else + moveItemInDatabase(context, item, container, screen, cellX, cellY); + } + } + + /** + * Move an item in the DB to a new <container, screen, cellX, cellY> + */ + static void moveItemInDatabase(Context context, ItemInfo item, long container, int screen, + int cellX, int cellY) { + item.container = container; + item.screen = screen; + item.cellX = cellX; + item.cellY = cellY; + + final ContentValues values = new ContentValues(); + final ContentResolver cr = context.getContentResolver(); + + values.put(LauncherSettings.Favorites.CONTAINER, item.container); + values.put(LauncherSettings.Favorites.CELLX, item.cellX); + values.put(LauncherSettings.Favorites.CELLY, item.cellY); + values.put(LauncherSettings.Favorites.SCREEN, item.screen); + + cr.update(LauncherSettings.Favorites.getContentUri(item.id, false), values, null, null); + } + + /** + * Returns true if the shortcuts already exists in the database. + * we identify a shortcut by its title and intent. + */ + static boolean shortcutExists(Context context, String title, Intent intent) { + final ContentResolver cr = context.getContentResolver(); + Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, + new String[] { "title", "intent" }, "title=? and intent=?", + new String[] { title, intent.toURI() }, null); + boolean result = false; + try { + result = c.moveToFirst(); + } finally { + c.close(); + } + return result; + } + + FolderInfo getFolderById(Context context, long id) { + final ContentResolver cr = context.getContentResolver(); + Cursor c = cr.query(LauncherSettings.Favorites.CONTENT_URI, null, + "_id=? and itemType=? or itemType=?", + new String[] { String.valueOf(id), + String.valueOf(LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER), + String.valueOf(LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER) }, null); + + try { + if (c.moveToFirst()) { + final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE); + final int titleIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE); + final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER); + final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN); + final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX); + final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY); + + FolderInfo folderInfo = null; + switch (c.getInt(itemTypeIndex)) { + case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER: + folderInfo = findOrMakeUserFolder(mFolders, id); + break; + case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER: + folderInfo = findOrMakeLiveFolder(mFolders, id); + break; + } + + folderInfo.title = c.getString(titleIndex); + folderInfo.id = id; + folderInfo.container = c.getInt(containerIndex); + folderInfo.screen = c.getInt(screenIndex); + folderInfo.cellX = c.getInt(cellXIndex); + folderInfo.cellY = c.getInt(cellYIndex); + + return folderInfo; + } + } finally { + c.close(); + } + + return null; + } + + /** + * Add an item to the database in a specified container. Sets the container, screen, cellX and + * cellY fields of the item. Also assigns an ID to the item. + */ + static void addItemToDatabase(Context context, ItemInfo item, long container, + int screen, int cellX, int cellY, boolean notify) { + item.container = container; + item.screen = screen; + item.cellX = cellX; + item.cellY = cellY; + + final ContentValues values = new ContentValues(); + final ContentResolver cr = context.getContentResolver(); + + item.onAddToDatabase(values); + + Uri result = cr.insert(notify ? LauncherSettings.Favorites.CONTENT_URI : + LauncherSettings.Favorites.CONTENT_URI_NO_NOTIFICATION, values); + + if (result != null) { + item.id = Integer.parseInt(result.getPathSegments().get(1)); + } + } + + /** + * Update an item to the database in a specified container. + */ + static void updateItemInDatabase(Context context, ItemInfo item) { + final ContentValues values = new ContentValues(); + final ContentResolver cr = context.getContentResolver(); + + item.onAddToDatabase(values); + + cr.update(LauncherSettings.Favorites.getContentUri(item.id, false), values, null, null); + } + + /** + * Removes the specified item from the database + * @param context + * @param item + */ + static void deleteItemFromDatabase(Context context, ItemInfo item) { + final ContentResolver cr = context.getContentResolver(); + + cr.delete(LauncherSettings.Favorites.getContentUri(item.id, false), null, null); + } + + + /** + * Remove the contents of the specified folder from the database + */ + static void deleteUserFolderContentsFromDatabase(Context context, UserFolderInfo info) { + final ContentResolver cr = context.getContentResolver(); + + cr.delete(LauncherSettings.Favorites.getContentUri(info.id, false), null, null); + cr.delete(LauncherSettings.Favorites.CONTENT_URI, + LauncherSettings.Favorites.CONTAINER + "=" + info.id, null); + } +} |