diff options
Diffstat (limited to 'src')
18 files changed, 201 insertions, 125 deletions
diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java index 94f8fc875..85f58a1b1 100644 --- a/src/com/android/launcher3/Folder.java +++ b/src/com/android/launcher3/Folder.java @@ -301,14 +301,13 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList mFolderName.setHint(sHintText); // Convert to a string here to ensure that no other state associated with the text field // gets saved. - CharSequence newTitle = mFolderName.getText(); + String newTitle = mFolderName.getText().toString(); mInfo.setTitle(newTitle); LauncherModel.updateItemInDatabase(mLauncher, mInfo); if (commit) { sendCustomAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED, - String.format(getContext().getString(R.string.folder_renamed), - newTitle.toString())); + String.format(getContext().getString(R.string.folder_renamed), newTitle)); } // In order to clear the focus from the text field, we set the focus on ourself. This // ensures that every time the field is clicked, focus is gained, giving reliable behavior. diff --git a/src/com/android/launcher3/IconCache.java b/src/com/android/launcher3/IconCache.java index 3165337c2..432b33c6b 100644 --- a/src/com/android/launcher3/IconCache.java +++ b/src/com/android/launcher3/IconCache.java @@ -301,7 +301,7 @@ public class IconCache { c.close(); if (!itemsToRemove.isEmpty()) { mIconDb.getWritableDatabase().delete(IconDB.TABLE_NAME, - IconDB.COLUMN_ROWID + " IN ( " + TextUtils.join(", ", itemsToRemove) +" )", + Utilities.createDbSelectionQuery(IconDB.COLUMN_ROWID, itemsToRemove), null); } diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 9989abb6d..a75a09af7 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -93,17 +93,16 @@ import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; - import com.android.launcher3.DropTarget.DragObject; import com.android.launcher3.PagedView.PageSwitchListener; import com.android.launcher3.allapps.AllAppsContainerView; -import com.android.launcher3.allapps.AllAppsSearchBarController; import com.android.launcher3.compat.AppWidgetManagerCompat; import com.android.launcher3.compat.LauncherActivityInfoCompat; import com.android.launcher3.compat.LauncherAppsCompat; import com.android.launcher3.compat.UserHandleCompat; import com.android.launcher3.compat.UserManagerCompat; import com.android.launcher3.model.WidgetsModel; +import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.LongArrayMap; import com.android.launcher3.util.Thunk; import com.android.launcher3.widget.PendingAddWidgetInfo; @@ -554,32 +553,44 @@ public class Launcher extends Activity public boolean setLauncherCallbacks(LauncherCallbacks callbacks) { mLauncherCallbacks = callbacks; mLauncherCallbacks.setLauncherSearchCallback(new Launcher.LauncherSearchCallbacks() { - private boolean mImportanceStored = false; + private boolean mWorkspaceImportanceStored = false; + private boolean mHotseatImportanceStored = false; private int mWorkspaceImportanceForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_AUTO; private int mHotseatImportanceForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_AUTO; @Override public void onSearchOverlayOpened() { - if (mImportanceStored) { + if (mWorkspaceImportanceStored || mHotseatImportanceStored) { return; } // The underlying workspace and hotseat are temporarily suppressed by the search // overlay. So they sholudn't be accessible. - mWorkspaceImportanceForAccessibility = mWorkspace.getImportantForAccessibility(); - mHotseatImportanceForAccessibility = mHotseat.getImportantForAccessibility(); - mWorkspace.setImportantForAccessibility( - View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS); - mHotseat.setImportantForAccessibility( - View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS); - mImportanceStored = true; + if (mWorkspace != null) { + mWorkspaceImportanceForAccessibility = + mWorkspace.getImportantForAccessibility(); + mWorkspace.setImportantForAccessibility( + View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS); + mWorkspaceImportanceStored = true; + } + if (mHotseat != null) { + mHotseatImportanceForAccessibility = mHotseat.getImportantForAccessibility(); + mHotseat.setImportantForAccessibility( + View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS); + mHotseatImportanceStored = true; + } } @Override public void onSearchOverlayClosed() { - mWorkspace.setImportantForAccessibility(mWorkspaceImportanceForAccessibility); - mHotseat.setImportantForAccessibility(mHotseatImportanceForAccessibility); - mImportanceStored = false; + if (mWorkspaceImportanceStored && mWorkspace != null) { + mWorkspace.setImportantForAccessibility(mWorkspaceImportanceForAccessibility); + } + if (mHotseatImportanceStored && mHotseat != null) { + mHotseat.setImportantForAccessibility(mHotseatImportanceForAccessibility); + } + mWorkspaceImportanceStored = false; + mHotseatImportanceStored = false; } }); return true; @@ -3436,7 +3447,7 @@ public class Launcher extends Activity */ private void tryAndUpdatePredictedApps() { if (mLauncherCallbacks != null) { - List<ComponentName> apps = mLauncherCallbacks.getPredictedApps(); + List<ComponentKey> apps = mLauncherCallbacks.getPredictedApps(); if (!apps.isEmpty()) { mAppsView.setPredictedApps(apps); } diff --git a/src/com/android/launcher3/LauncherCallbacks.java b/src/com/android/launcher3/LauncherCallbacks.java index e73275400..56db7747c 100644 --- a/src/com/android/launcher3/LauncherCallbacks.java +++ b/src/com/android/launcher3/LauncherCallbacks.java @@ -8,6 +8,7 @@ import android.view.Menu; import android.view.View; import android.view.ViewGroup; import com.android.launcher3.allapps.AllAppsSearchBarController; +import com.android.launcher3.util.ComponentKey; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -92,7 +93,7 @@ public interface LauncherCallbacks { public boolean overrideWallpaperDimensions(); public boolean isLauncherPreinstalled(); public AllAppsSearchBarController getAllAppsSearchBarController(); - public List<ComponentName> getPredictedApps(); + public List<ComponentKey> getPredictedApps(); /** * Returning true will immediately result in a call to {@link #setLauncherOverlayView(ViewGroup, diff --git a/src/com/android/launcher3/LauncherExtension.java b/src/com/android/launcher3/LauncherExtension.java index fafb070ec..857ec57a7 100644 --- a/src/com/android/launcher3/LauncherExtension.java +++ b/src/com/android/launcher3/LauncherExtension.java @@ -12,6 +12,7 @@ import android.view.Menu; import android.view.View; import android.view.ViewGroup; import com.android.launcher3.allapps.AllAppsSearchBarController; +import com.android.launcher3.util.ComponentKey; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -253,7 +254,7 @@ public class LauncherExtension extends Launcher { } @Override - public List<ComponentName> getPredictedApps() { + public List<ComponentKey> getPredictedApps() { return new ArrayList<>(); } diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index a132e919a..d2112afb4 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -20,7 +20,6 @@ import android.app.SearchManager; import android.appwidget.AppWidgetProviderInfo; import android.content.BroadcastReceiver; import android.content.ComponentName; -import android.content.ContentProviderClient; import android.content.ContentProviderOperation; import android.content.ContentResolver; import android.content.ContentValues; @@ -43,7 +42,6 @@ import android.os.HandlerThread; import android.os.Looper; import android.os.Parcelable; import android.os.Process; -import android.os.RemoteException; import android.os.SystemClock; import android.os.TransactionTooLargeException; import android.provider.BaseColumns; @@ -242,6 +240,7 @@ public class LauncherModel extends BroadcastReceiver mApp = app; mBgAllAppsList = new AllAppsList(iconCache, appFilter); + mBgWidgetsModel = new WidgetsModel(context, iconCache, appFilter); mIconCache = iconCache; final Resources res = context.getResources(); @@ -1866,6 +1865,7 @@ public class LauncherModel extends BroadcastReceiver int itemType = c.getInt(itemTypeIndex); boolean restored = 0 != c.getInt(restoredIndex); boolean allowMissingTarget = false; + container = c.getInt(containerIndex); switch (itemType) { case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: @@ -2004,7 +2004,6 @@ public class LauncherModel extends BroadcastReceiver continue; } - container = c.getInt(containerIndex); boolean useLowResIcon = container >= 0 && c.getInt(rankIndex) >= FolderIcon.NUM_ITEMS_IN_PREVIEW; @@ -2111,7 +2110,6 @@ public class LauncherModel extends BroadcastReceiver // Do not trim the folder label, as is was set by the user. folderInfo.title = c.getString(titleIndex); folderInfo.id = id; - container = c.getInt(containerIndex); folderInfo.container = container; folderInfo.screenId = c.getInt(screenIndex); folderInfo.cellX = c.getInt(cellXIndex); @@ -2233,7 +2231,6 @@ public class LauncherModel extends BroadcastReceiver appWidgetInfo.spanX = c.getInt(spanXIndex); appWidgetInfo.spanY = c.getInt(spanYIndex); - container = c.getInt(containerIndex); if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP && container != LauncherSettings.Favorites.CONTAINER_HOTSEAT) { Log.e(TAG, "Widget found where container != " + @@ -2241,7 +2238,7 @@ public class LauncherModel extends BroadcastReceiver continue; } - appWidgetInfo.container = c.getInt(containerIndex); + appWidgetInfo.container = container; // check & update map of what's occupied if (!checkItemPlacement(occupied, appWidgetInfo)) { itemsToRemove.add(id); @@ -2283,56 +2280,32 @@ public class LauncherModel extends BroadcastReceiver return; } - // Remove any empty folder - LongArrayMap<FolderInfo> emptyFolders = sBgFolders.clone(); - for (ItemInfo item: sBgItemsIdMap) { - long container = item.container; - if (emptyFolders.containsKey(container)) { - emptyFolders.remove(container); - } - } - for (FolderInfo folder : emptyFolders) { - long folderId = folder.id; - sBgFolders.remove(folderId); - sBgItemsIdMap.remove(folderId); - sBgWorkspaceItems.remove(folder); - itemsToRemove.add(folderId); - } - if (itemsToRemove.size() > 0) { - ContentProviderClient client = contentResolver.acquireContentProviderClient( - contentUri); // Remove dead items - for (long id : itemsToRemove) { - if (DEBUG_LOADERS) { - Log.d(TAG, "Removed id = " + id); - } - // Don't notify content observers - try { - client.delete(LauncherSettings.Favorites.getContentUri(id), null, null); - } catch (RemoteException e) { - Log.w(TAG, "Could not remove id = " + id); - } + contentResolver.delete(LauncherSettings.Favorites.CONTENT_URI, + Utilities.createDbSelectionQuery( + LauncherSettings.Favorites._ID, itemsToRemove), null); + if (DEBUG_LOADERS) { + Log.d(TAG, "Removed = " + Utilities.createDbSelectionQuery( + LauncherSettings.Favorites._ID, itemsToRemove)); + } + + // Remove any empty folder + for (long folderId : LauncherAppState.getLauncherProvider() + .deleteEmptyFolders()) { + sBgWorkspaceItems.remove(sBgFolders.get(folderId)); + sBgFolders.remove(folderId); + sBgItemsIdMap.remove(folderId); } } if (restoredRows.size() > 0) { - ContentProviderClient updater = contentResolver.acquireContentProviderClient( - contentUri); // Update restored items that no longer require special handling - try { - StringBuilder selectionBuilder = new StringBuilder(); - selectionBuilder.append(LauncherSettings.Favorites._ID); - selectionBuilder.append(" IN ("); - selectionBuilder.append(TextUtils.join(", ", restoredRows)); - selectionBuilder.append(")"); - ContentValues values = new ContentValues(); - values.put(LauncherSettings.Favorites.RESTORED, 0); - updater.update(LauncherSettings.Favorites.CONTENT_URI, - values, selectionBuilder.toString(), null); - } catch (RemoteException e) { - Log.w(TAG, "Could not update restored rows"); - } + ContentValues values = new ContentValues(); + values.put(LauncherSettings.Favorites.RESTORED, 0); + contentResolver.update(LauncherSettings.Favorites.CONTENT_URI, values, + Utilities.createDbSelectionQuery( + LauncherSettings.Favorites._ID, restoredRows), null); } if (!isSdCardReady && !sPendingPackages.isEmpty()) { @@ -2342,9 +2315,6 @@ public class LauncherModel extends BroadcastReceiver } sBgWorkspaceScreens.addAll(loadWorkspaceScreensDb(mContext)); - // Log to disk - Launcher.addDumpLog(TAG, "11683562 - sBgWorkspaceScreens: " + - TextUtils.join(", ", sBgWorkspaceScreens), true); // Remove any empty screens ArrayList<Long> unusedScreens = new ArrayList<Long>(sBgWorkspaceScreens); @@ -2358,10 +2328,6 @@ public class LauncherModel extends BroadcastReceiver // If there are any empty screens remove them, and update. if (unusedScreens.size() != 0) { - // Log to disk - Launcher.addDumpLog(TAG, "11683562 - unusedScreens (to be removed): " + - TextUtils.join(", ", unusedScreens), true); - sBgWorkspaceScreens.removeAll(unusedScreens); updateWorkspaceScreenOrder(context, sBgWorkspaceScreens); } @@ -3346,10 +3312,12 @@ public class LauncherModel extends BroadcastReceiver public void loadAndBindWidgetsAndShortcuts(final Context context, final Callbacks callbacks, final boolean refresh) { - runOnWorkerThread(new Runnable(){ + runOnWorkerThread(new Runnable() { @Override public void run() { - final WidgetsModel model = createWidgetsModel(context, refresh); + updateWidgetsModel(context, refresh); + final WidgetsModel model = mBgWidgetsModel.clone(); + mHandler.post(new Runnable() { @Override public void run() { @@ -3359,7 +3327,6 @@ public class LauncherModel extends BroadcastReceiver } } }); - mBgWidgetsModel = model; // update the Widget entries inside DB on the worker thread. LauncherAppState.getInstance().getWidgetCache().removeObsoletePreviews( model.getRawList()); @@ -3372,15 +3339,13 @@ public class LauncherModel extends BroadcastReceiver * * @see #loadAndBindWidgetsAndShortcuts */ - @Thunk WidgetsModel createWidgetsModel(Context context, boolean refresh) { + @Thunk void updateWidgetsModel(Context context, boolean refresh) { PackageManager packageManager = context.getPackageManager(); final ArrayList<Object> widgetsAndShortcuts = new ArrayList<Object>(); widgetsAndShortcuts.addAll(getWidgetProviders(context, refresh)); Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT); widgetsAndShortcuts.addAll(packageManager.queryIntentActivities(shortcutsIntent, 0)); - WidgetsModel model = new WidgetsModel(context); - model.addWidgetsAndShortcuts(widgetsAndShortcuts); - return model; + mBgWidgetsModel.setWidgetsAndShortcuts(widgetsAndShortcuts); } @Thunk static boolean isPackageDisabled(Context context, String packageName, diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java index 71ddb1ab1..3ebc30737 100644 --- a/src/com/android/launcher3/LauncherProvider.java +++ b/src/com/android/launcher3/LauncherProvider.java @@ -62,6 +62,7 @@ import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; +import java.util.List; public class LauncherProvider extends ContentProvider { private static final String TAG = "Launcher.LauncherProvider"; @@ -99,6 +100,7 @@ public class LauncherProvider extends ContentProvider { public void setLauncherProviderChangeListener(LauncherProviderChangeListener listener) { mListener = listener; + mOpenHelper.mListener = mListener; } @Override @@ -262,6 +264,42 @@ public class LauncherProvider extends ContentProvider { return null; } + /** + * Deletes any empty folder from the DB. + * @return Ids of deleted folders. + */ + public List<Long> deleteEmptyFolders() { + ArrayList<Long> folderIds = new ArrayList<Long>(); + SQLiteDatabase db = mOpenHelper.getWritableDatabase(); + db.beginTransaction(); + try { + // Select folders whose id do not match any container value. + String selection = LauncherSettings.Favorites.ITEM_TYPE + " = " + + LauncherSettings.Favorites.ITEM_TYPE_FOLDER + " AND " + + LauncherSettings.Favorites._ID + " NOT IN (SELECT " + + LauncherSettings.Favorites.CONTAINER + " FROM " + + TABLE_FAVORITES + ")"; + Cursor c = db.query(TABLE_FAVORITES, + new String[] {LauncherSettings.Favorites._ID}, + selection, null, null, null, null); + while (c.moveToNext()) { + folderIds.add(c.getLong(0)); + } + c.close(); + if (folderIds.size() > 0) { + db.delete(TABLE_FAVORITES, Utilities.createDbSelectionQuery( + LauncherSettings.Favorites._ID, folderIds), null); + } + db.setTransactionSuccessful(); + } catch (SQLException ex) { + Log.e(TAG, ex.getMessage(), ex); + folderIds.clear(); + } finally { + db.endTransaction(); + } + return folderIds; + } + private void notifyListeners() { // always notify the backup agent LauncherBackupAgentHelper.dataChanged(getContext()); @@ -270,18 +308,6 @@ public class LauncherProvider extends ContentProvider { } } - @Thunk void notifyAppWidgetHostReset() { - new MainThreadExecutor().execute(new Runnable() { - - @Override - public void run() { - if (mListener != null) { - mListener.onAppWidgetHostReset(); - } - } - }); - } - @Thunk static void addModifiedTime(ContentValues values) { values.put(LauncherSettings.ChangeLogColumns.MODIFIED, System.currentTimeMillis()); } @@ -429,6 +455,7 @@ public class LauncherProvider extends ContentProvider { SQLiteDatabase.deleteDatabase(dbFile); } mOpenHelper = new DatabaseHelper(getContext()); + mOpenHelper.mListener = mListener; } private static class DatabaseHelper extends SQLiteOpenHelper implements LayoutParserCallback { @@ -439,6 +466,8 @@ public class LauncherProvider extends ContentProvider { private boolean mNewDbCreated = false; + @Thunk LauncherProviderChangeListener mListener; + DatabaseHelper(Context context) { super(context, LauncherFiles.LAUNCHER_DB, null, DATABASE_VERSION); mContext = context; @@ -508,7 +537,15 @@ public class LauncherProvider extends ContentProvider { * want to re-call {@link AppWidgetHost#startListening()} to ensure * callbacks are correctly set. */ - LauncherAppState.getLauncherProvider().notifyAppWidgetHostReset(); + new MainThreadExecutor().execute(new Runnable() { + + @Override + public void run() { + if (mListener != null) { + mListener.onAppWidgetHostReset(); + } + } + }); } // Fresh and clean launcher DB. diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java index 2d8a1b1cf..3b06c2093 100644 --- a/src/com/android/launcher3/Utilities.java +++ b/src/com/android/launcher3/Utilities.java @@ -54,12 +54,14 @@ import android.util.SparseArray; import android.util.TypedValue; import android.view.View; import android.widget.Toast; + import junit.framework.Assert; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Comparator; +import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -677,4 +679,8 @@ public final class Utilities { return (int) Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, size, metrics)); } + + public static String createDbSelectionQuery(String columnName, Iterable<?> values) { + return String.format(Locale.ENGLISH, "%s IN (%s)", columnName, TextUtils.join(", ", values)); + } } diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java index 5ca0ac8d6..629387ed0 100644 --- a/src/com/android/launcher3/WidgetPreviewLoader.java +++ b/src/com/android/launcher3/WidgetPreviewLoader.java @@ -59,7 +59,7 @@ public class WidgetPreviewLoader { * Note: synchronized block used for this variable is expensive and the block should always * be posted to a background thread. */ - @Thunk Set<Bitmap> mUnusedBitmaps = + @Thunk final Set<Bitmap> mUnusedBitmaps = Collections.newSetFromMap(new WeakHashMap<Bitmap, Boolean>()); private final Context mContext; @@ -540,7 +540,7 @@ public class WidgetPreviewLoader { */ public class PreviewLoadRequest { - private final PreviewLoadTask mTask; + @Thunk final PreviewLoadTask mTask; public PreviewLoadRequest(PreviewLoadTask task) { mTask = task; diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java index 4542586a6..d56e9fc1e 100644 --- a/src/com/android/launcher3/allapps/AllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java @@ -207,7 +207,7 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc /** * Sets the current set of predicted apps. */ - public void setPredictedApps(List<ComponentName> apps) { + public void setPredictedApps(List<ComponentKey> apps) { mApps.setPredictedApps(apps); } diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java index b7b6ed7fc..aa73c74cf 100644 --- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java +++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java @@ -15,14 +15,14 @@ */ package com.android.launcher3.allapps; -import android.content.ComponentName; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.util.Log; - import com.android.launcher3.AppInfo; import com.android.launcher3.Launcher; +import com.android.launcher3.LauncherAppState; import com.android.launcher3.compat.AlphabeticIndexCompat; +import com.android.launcher3.compat.UserHandleCompat; import com.android.launcher3.model.AppNameComparator; import com.android.launcher3.util.ComponentKey; @@ -159,7 +159,7 @@ public class AlphabeticalAppsList { // The set of sections that we allow fast-scrolling to (includes non-merged sections) private List<FastScrollSectionInfo> mFastScrollerSections = new ArrayList<>(); // The set of predicted app component names - private List<ComponentName> mPredictedAppComponents = new ArrayList<>(); + private List<ComponentKey> mPredictedAppComponents = new ArrayList<>(); // The set of predicted apps resolved from the component names and the current set of apps private List<AppInfo> mPredictedApps = new ArrayList<>(); // The of ordered component names as a result of a search query @@ -268,7 +268,7 @@ public class AlphabeticalAppsList { * Sets the current set of predicted apps. Since this can be called before we get the full set * of applications, we should merge the results only in onAppsUpdated() which is idempotent. */ - public void setPredictedApps(List<ComponentName> apps) { + public void setPredictedApps(List<ComponentKey> apps) { mPredictedAppComponents.clear(); mPredictedAppComponents.addAll(apps); onAppsUpdated(); @@ -386,21 +386,27 @@ public class AlphabeticalAppsList { if (DEBUG_PREDICTIONS) { if (mPredictedAppComponents.isEmpty() && !mApps.isEmpty()) { - mPredictedAppComponents.add(mApps.get(0).componentName); - mPredictedAppComponents.add(mApps.get(0).componentName); - mPredictedAppComponents.add(mApps.get(0).componentName); - mPredictedAppComponents.add(mApps.get(0).componentName); + mPredictedAppComponents.add(new ComponentKey(mApps.get(0).componentName, + UserHandleCompat.myUserHandle())); + mPredictedAppComponents.add(new ComponentKey(mApps.get(0).componentName, + UserHandleCompat.myUserHandle())); + mPredictedAppComponents.add(new ComponentKey(mApps.get(0).componentName, + UserHandleCompat.myUserHandle())); + mPredictedAppComponents.add(new ComponentKey(mApps.get(0).componentName, + UserHandleCompat.myUserHandle())); } } // Process the predicted app components mPredictedApps.clear(); if (mPredictedAppComponents != null && !mPredictedAppComponents.isEmpty() && !hasFilter()) { - for (ComponentName cn : mPredictedAppComponents) { - for (AppInfo info : mApps) { - if (cn.equals(info.componentName)) { - mPredictedApps.add(info); - break; + for (ComponentKey ck : mPredictedAppComponents) { + AppInfo info = mComponentToAppMap.get(ck); + if (info != null) { + mPredictedApps.add(info); + } else { + if (LauncherAppState.isDogfoodBuild()) { + Log.e(TAG, "Predicted app not found: " + ck.flattenToString(mLauncher)); } } // Stop at the number of predicted apps diff --git a/src/com/android/launcher3/allapps/DefaultAppSearchController.java b/src/com/android/launcher3/allapps/DefaultAppSearchController.java index a61df3a7d..20924af94 100644 --- a/src/com/android/launcher3/allapps/DefaultAppSearchController.java +++ b/src/com/android/launcher3/allapps/DefaultAppSearchController.java @@ -83,7 +83,7 @@ final class DefaultAppSearchController extends AllAppsSearchBarController mDismissSearchButtonView = mSearchBarContainerView.findViewById(R.id.dismiss_search_button); mDismissSearchButtonView.setOnClickListener(this); mSearchBarEditView = (AllAppsSearchEditView) - mSearchBarContainerView.findViewById(R.id.search_box); + mSearchBarContainerView.findViewById(R.id.search_box_input); mSearchBarEditView.addTextChangedListener(this); mSearchBarEditView.setOnEditorActionListener(this); mSearchBarEditView.setOnBackKeyListener( diff --git a/src/com/android/launcher3/compat/LauncherAppsCompatVL.java b/src/com/android/launcher3/compat/LauncherAppsCompatVL.java index c862ffc0a..fbf91b548 100644 --- a/src/com/android/launcher3/compat/LauncherAppsCompatVL.java +++ b/src/com/android/launcher3/compat/LauncherAppsCompatVL.java @@ -51,7 +51,7 @@ public class LauncherAppsCompatVL extends LauncherAppsCompat { List<LauncherActivityInfo> list = mLauncherApps.getActivityList(packageName, user.getUser()); if (list.size() == 0) { - return Collections.EMPTY_LIST; + return Collections.emptyList(); } ArrayList<LauncherActivityInfoCompat> compatList = new ArrayList<LauncherActivityInfoCompat>(list.size()); diff --git a/src/com/android/launcher3/compat/UserHandleCompat.java b/src/com/android/launcher3/compat/UserHandleCompat.java index d8e60b875..ab4b7216b 100644 --- a/src/com/android/launcher3/compat/UserHandleCompat.java +++ b/src/com/android/launcher3/compat/UserHandleCompat.java @@ -41,7 +41,7 @@ public class UserHandleCompat { } } - static UserHandleCompat fromUser(UserHandle user) { + public static UserHandleCompat fromUser(UserHandle user) { if (user == null) { return null; } else { diff --git a/src/com/android/launcher3/compat/UserManagerCompatVL.java b/src/com/android/launcher3/compat/UserManagerCompatVL.java index f6434c5b2..dd7a72617 100644 --- a/src/com/android/launcher3/compat/UserManagerCompatVL.java +++ b/src/com/android/launcher3/compat/UserManagerCompatVL.java @@ -46,7 +46,7 @@ public class UserManagerCompatVL extends UserManagerCompatV17 { public List<UserHandleCompat> getUserProfiles() { List<UserHandle> users = mUserManager.getUserProfiles(); if (users == null) { - return Collections.EMPTY_LIST; + return Collections.emptyList(); } ArrayList<UserHandleCompat> compatUsers = new ArrayList<UserHandleCompat>( users.size()); diff --git a/src/com/android/launcher3/model/WidgetsModel.java b/src/com/android/launcher3/model/WidgetsModel.java index 625d4d696..09a3242b5 100644 --- a/src/com/android/launcher3/model/WidgetsModel.java +++ b/src/com/android/launcher3/model/WidgetsModel.java @@ -1,10 +1,12 @@ package com.android.launcher3.model; +import android.content.ComponentName; import android.content.Context; import android.content.pm.ResolveInfo; import android.util.Log; +import com.android.launcher3.AppFilter; import com.android.launcher3.IconCache; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherAppWidgetProviderInfo; @@ -39,26 +41,32 @@ public class WidgetsModel { private final Comparator mWidgetAndShortcutNameComparator; private final Comparator mAppNameComparator; private final IconCache mIconCache; + private final AppFilter mAppFilter; private AlphabeticIndexCompat mIndexer; - public WidgetsModel(Context context) { + public WidgetsModel(Context context, IconCache iconCache, AppFilter appFilter) { mWidgetAndShortcutNameComparator = new WidgetsAndShortcutNameComparator(context); mAppNameComparator = (new AppNameComparator(context)).getAppInfoComparator(); - mIconCache = LauncherAppState.getInstance().getIconCache(); + mIconCache = iconCache; + mAppFilter = appFilter; mIndexer = new AlphabeticIndexCompat(context); } private WidgetsModel(WidgetsModel model) { mPackageItemInfos = (ArrayList<PackageItemInfo>) model.mPackageItemInfos.clone(); mWidgetsList = (HashMap<PackageItemInfo, ArrayList<Object>>) model.mWidgetsList.clone(); - // mRawList is not copied as should not be needed. + mRawList = (ArrayList<Object>) model.mRawList.clone(); mWidgetAndShortcutNameComparator = model.mWidgetAndShortcutNameComparator; mAppNameComparator = model.mAppNameComparator; mIconCache = model.mIconCache; + mAppFilter = model.mAppFilter; } // Access methods that may be deleted if the private fields are made package-private. public int getPackageSize() { + if (mPackageItemInfos == null) { + return 0; + } return mPackageItemInfos.size(); } @@ -78,7 +86,7 @@ public class WidgetsModel { return mRawList; } - public void addWidgetsAndShortcuts(ArrayList<Object> rawWidgetsShortcuts) { + public void setWidgetsAndShortcuts(ArrayList<Object> rawWidgetsShortcuts) { Utilities.assertWorkerThread(); mRawList = rawWidgetsShortcuts; if (DEBUG) { @@ -96,15 +104,27 @@ public class WidgetsModel { // add and update. for (Object o: rawWidgetsShortcuts) { String packageName = ""; + ComponentName componentName = null; if (o instanceof LauncherAppWidgetProviderInfo) { LauncherAppWidgetProviderInfo widgetInfo = (LauncherAppWidgetProviderInfo) o; + componentName = widgetInfo.provider; packageName = widgetInfo.provider.getPackageName(); } else if (o instanceof ResolveInfo) { ResolveInfo resolveInfo = (ResolveInfo) o; + componentName = new ComponentName(resolveInfo.activityInfo.packageName, + resolveInfo.activityInfo.name); packageName = resolveInfo.activityInfo.packageName; - } else { - Log.e(TAG, String.format("addWidgetsAndShortcuts, nothing added for class=%s", + } + + if (componentName == null) { + Log.e(TAG, String.format("Widget cannot be set for class=%s", o.getClass().toString())); + continue; + } + if (mAppFilter != null && !mAppFilter.shouldShowApp(componentName)) { + Log.d(TAG, String.format("%s is filtered and not added to the widget tray.", + packageName)); + continue; } PackageItemInfo pInfo = tmpPackageItemInfos.get(packageName); diff --git a/src/com/android/launcher3/util/ComponentKey.java b/src/com/android/launcher3/util/ComponentKey.java index 0f17f009e..6a7df4318 100644 --- a/src/com/android/launcher3/util/ComponentKey.java +++ b/src/com/android/launcher3/util/ComponentKey.java @@ -17,8 +17,9 @@ package com.android.launcher3.util; */ import android.content.ComponentName; - +import android.content.Context; import com.android.launcher3.compat.UserHandleCompat; +import com.android.launcher3.compat.UserManagerCompat; import java.util.Arrays; @@ -38,6 +39,35 @@ public class ComponentKey { } + /** + * Creates a new component key from an encoded component key string in the form of + * [flattenedComponentString#userId]. If the userId is not present, then it defaults + * to the current user. + */ + public ComponentKey(Context context, String componentKeyStr) { + int userDelimiterIndex = componentKeyStr.indexOf("#"); + if (userDelimiterIndex != -1) { + String componentStr = componentKeyStr.substring(0, userDelimiterIndex); + Long componentUser = Long.valueOf(componentKeyStr.substring(userDelimiterIndex + 1)); + componentName = ComponentName.unflattenFromString(componentStr); + user = UserManagerCompat.getInstance(context) + .getUserForSerialNumber(componentUser.longValue()); + } else { + // No user provided, default to the current user + componentName = ComponentName.unflattenFromString(componentKeyStr); + user = UserHandleCompat.myUserHandle(); + } + mHashCode = Arrays.hashCode(new Object[] {componentName, user}); + } + + /** + * Encodes a component key as a string of the form [flattenedComponentString#userId]. + */ + public String flattenToString(Context context) { + return componentName.flattenToString() + "#" + + UserManagerCompat.getInstance(context).getSerialNumberForUser(user); + } + @Override public int hashCode() { return mHashCode; diff --git a/src/com/android/launcher3/widget/WidgetsListAdapter.java b/src/com/android/launcher3/widget/WidgetsListAdapter.java index e82c0a631..d07c9553a 100644 --- a/src/com/android/launcher3/widget/WidgetsListAdapter.java +++ b/src/com/android/launcher3/widget/WidgetsListAdapter.java @@ -54,7 +54,7 @@ import java.util.List; public class WidgetsListAdapter extends Adapter<WidgetsRowViewHolder> { private static final String TAG = "WidgetsListAdapter"; - private static final boolean DEBUG = true; + private static final boolean DEBUG = false; private Launcher mLauncher; private LayoutInflater mLayoutInflater; |