summaryrefslogtreecommitdiffstats
path: root/core/java/android/app/SuggestionsAdapter.java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android/app/SuggestionsAdapter.java')
-rw-r--r--core/java/android/app/SuggestionsAdapter.java146
1 files changed, 103 insertions, 43 deletions
diff --git a/core/java/android/app/SuggestionsAdapter.java b/core/java/android/app/SuggestionsAdapter.java
index 90f8c50..12be97c 100644
--- a/core/java/android/app/SuggestionsAdapter.java
+++ b/core/java/android/app/SuggestionsAdapter.java
@@ -20,6 +20,7 @@ import android.app.SearchManager.DialogCursorProtocol;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.ContentResolver.OpenResourceIdResult;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -27,7 +28,6 @@ import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
-import android.graphics.drawable.DrawableContainer;
import android.graphics.drawable.StateListDrawable;
import android.net.Uri;
import android.os.Bundle;
@@ -36,12 +36,13 @@ import android.text.Html;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
+import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.Filter;
import android.widget.ImageView;
import android.widget.ResourceCursorAdapter;
import android.widget.TextView;
-import android.widget.Filter;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -57,6 +58,7 @@ class SuggestionsAdapter extends ResourceCursorAdapter {
private static final boolean DBG = false;
private static final String LOG_TAG = "SuggestionsAdapter";
+ private static final int QUERY_LIMIT = 50;
private SearchManager mSearchManager;
private SearchDialog mSearchDialog;
@@ -185,7 +187,7 @@ class SuggestionsAdapter extends ResourceCursorAdapter {
mSearchDialog.getWindow().getDecorView().post(mStartSpinnerRunnable);
}
try {
- final Cursor cursor = mSearchManager.getSuggestions(mSearchable, query);
+ final Cursor cursor = mSearchManager.getSuggestions(mSearchable, query, QUERY_LIMIT);
// trigger fill window so the spinner stays up until the results are copied over and
// closer to being ready
if (!mGlobalSearchMode && cursor != null) cursor.getCount();
@@ -288,12 +290,16 @@ class SuggestionsAdapter extends ResourceCursorAdapter {
* @param cursor The cursor
* @param position The position that was clicked.
*/
- void callCursorOnClick(Cursor cursor, int position) {
+ void callCursorOnClick(Cursor cursor, int position, int actionKey, String actionMsg) {
if (!mGlobalSearchMode) return;
- final Bundle request = new Bundle(1);
+ final Bundle request = new Bundle(5);
request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.CLICK);
request.putInt(DialogCursorProtocol.CLICK_SEND_POSITION, position);
request.putInt(DialogCursorProtocol.CLICK_SEND_MAX_DISPLAY_POS, mMaxDisplayed);
+ if (actionKey != KeyEvent.KEYCODE_UNKNOWN) {
+ request.putInt(DialogCursorProtocol.CLICK_SEND_ACTION_KEY, actionKey);
+ request.putString(DialogCursorProtocol.CLICK_SEND_ACTION_MSG, actionMsg);
+ }
final Bundle response = cursor.respond(request);
mMaxDisplayed = -1;
mListItemToSelect = response.getInt(
@@ -301,6 +307,23 @@ class SuggestionsAdapter extends ResourceCursorAdapter {
}
/**
+ * Tell the cursor that a search was started without using a suggestion.
+ *
+ * @param query The search query.
+ */
+ void reportSearch(String query) {
+ if (!mGlobalSearchMode) return;
+ Cursor cursor = getCursor();
+ if (cursor == null) return;
+ final Bundle request = new Bundle(3);
+ request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.SEARCH);
+ request.putString(DialogCursorProtocol.SEARCH_SEND_QUERY, query);
+ request.putInt(DialogCursorProtocol.SEARCH_SEND_MAX_DISPLAY_POS, mMaxDisplayed);
+ // the response is always empty
+ cursor.respond(request);
+ }
+
+ /**
* Tags the view with cached child view look-ups.
*/
@Override
@@ -378,7 +401,7 @@ class SuggestionsAdapter extends ResourceCursorAdapter {
Drawable.ConstantState cachedBg = mBackgroundsCache.get(backgroundColor);
if (cachedBg != null) {
if (DBG) Log.d(LOG_TAG, "Background cache hit for color " + backgroundColor);
- return cachedBg.newDrawable();
+ return cachedBg.newDrawable(mProviderContext.getResources());
}
if (DBG) Log.d(LOG_TAG, "Creating new background for color " + backgroundColor);
ColorDrawable transparent = new ColorDrawable(0);
@@ -550,54 +573,91 @@ class SuggestionsAdapter extends ResourceCursorAdapter {
if (drawableId == null || drawableId.length() == 0 || "0".equals(drawableId)) {
return null;
}
-
- // First, check the cache.
- Drawable.ConstantState cached = mOutsideDrawablesCache.get(drawableId);
- if (cached != null) {
- if (DBG) Log.d(LOG_TAG, "Found icon in cache: " + drawableId);
- return cached.newDrawable();
- }
-
- Drawable drawable = null;
try {
- // Not cached, try using it as a plain resource ID in the provider's context.
+ // First, see if it's just an integer
int resourceId = Integer.parseInt(drawableId);
+ // It's an int, look for it in the cache
+ String drawableUri = ContentResolver.SCHEME_ANDROID_RESOURCE
+ + "://" + mProviderContext.getPackageName() + "/" + resourceId;
+ // Must use URI as cache key, since ints are app-specific
+ Drawable drawable = checkIconCache(drawableUri);
+ if (drawable != null) {
+ return drawable;
+ }
+ // Not cached, find it by resource ID
drawable = mProviderContext.getResources().getDrawable(resourceId);
- if (DBG) Log.d(LOG_TAG, "Found icon by resource ID: " + drawableId);
+ // Stick it in the cache, using the URI as key
+ storeInIconCache(drawableUri, drawable);
+ return drawable;
} catch (NumberFormatException nfe) {
- // The id was not an integer resource id.
- // Let the ContentResolver handle content, android.resource and file URIs.
- try {
- Uri uri = Uri.parse(drawableId);
+ // It's not an integer, use it as a URI
+ Drawable drawable = checkIconCache(drawableId);
+ if (drawable != null) {
+ return drawable;
+ }
+ Uri uri = Uri.parse(drawableId);
+ drawable = getDrawable(uri);
+ storeInIconCache(drawableId, drawable);
+ return drawable;
+ } catch (Resources.NotFoundException nfe) {
+ // It was an integer, but it couldn't be found, bail out
+ Log.w(LOG_TAG, "Icon resource not found: " + drawableId);
+ return null;
+ }
+ }
+
+ /**
+ * Gets a drawable by URI, without using the cache.
+ *
+ * @return A drawable, or {@code null} if the drawable could not be loaded.
+ */
+ private Drawable getDrawable(Uri uri) {
+ try {
+ String scheme = uri.getScheme();
+ if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)) {
+ // Load drawables through Resources, to get the source density information
+ OpenResourceIdResult r =
+ mProviderContext.getContentResolver().getResourceId(uri);
+ try {
+ return r.r.getDrawable(r.id);
+ } catch (Resources.NotFoundException ex) {
+ throw new FileNotFoundException("Resource does not exist: " + uri);
+ }
+ } else {
+ // Let the ContentResolver handle content and file URIs.
InputStream stream = mProviderContext.getContentResolver().openInputStream(uri);
- if (stream != null) {
+ if (stream == null) {
+ throw new FileNotFoundException("Failed to open " + uri);
+ }
+ try {
+ return Drawable.createFromStream(stream, null);
+ } finally {
try {
- drawable = Drawable.createFromStream(stream, null);
- } finally {
- try {
- stream.close();
- } catch (IOException ex) {
- Log.e(LOG_TAG, "Error closing icon stream for " + uri, ex);
- }
+ stream.close();
+ } catch (IOException ex) {
+ Log.e(LOG_TAG, "Error closing icon stream for " + uri, ex);
}
}
- if (DBG) Log.d(LOG_TAG, "Opened icon input stream: " + drawableId);
- } catch (FileNotFoundException fnfe) {
- if (DBG) Log.d(LOG_TAG, "Icon stream not found: " + drawableId);
- // drawable = null;
}
+ } catch (FileNotFoundException fnfe) {
+ Log.w(LOG_TAG, "Icon not found: " + uri + ", " + fnfe.getMessage());
+ return null;
+ }
+ }
- // If we got a drawable for this resource id, then stick it in the
- // map so we don't do this lookup again.
- if (drawable != null) {
- mOutsideDrawablesCache.put(drawableId, drawable.getConstantState());
- }
- } catch (Resources.NotFoundException nfe) {
- if (DBG) Log.d(LOG_TAG, "Icon resource not found: " + drawableId);
- // drawable = null;
+ private Drawable checkIconCache(String resourceUri) {
+ Drawable.ConstantState cached = mOutsideDrawablesCache.get(resourceUri);
+ if (cached == null) {
+ return null;
}
+ if (DBG) Log.d(LOG_TAG, "Found icon in cache: " + resourceUri);
+ return cached.newDrawable();
+ }
- return drawable;
+ private void storeInIconCache(String resourceUri, Drawable drawable) {
+ if (drawable != null) {
+ mOutsideDrawablesCache.put(resourceUri, drawable.getConstantState());
+ }
}
/**
@@ -646,7 +706,7 @@ class SuggestionsAdapter extends ResourceCursorAdapter {
// Using containsKey() since we also store null values.
if (mOutsideDrawablesCache.containsKey(componentIconKey)) {
Drawable.ConstantState cached = mOutsideDrawablesCache.get(componentIconKey);
- return cached == null ? null : cached.newDrawable();
+ return cached == null ? null : cached.newDrawable(mProviderContext.getResources());
}
// Then try the activity or application icon
Drawable drawable = getActivityIcon(component);