Merge "Apply API feedback for ChooserTarget" into mnc-dev
diff --git a/api/current.txt b/api/current.txt
index 23b0395..4369bf0 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -28633,10 +28633,10 @@
 package android.service.chooser {
 
   public final class ChooserTarget implements android.os.Parcelable {
-    ctor public ChooserTarget(java.lang.CharSequence, android.graphics.Bitmap, float, android.app.PendingIntent);
-    ctor public ChooserTarget(java.lang.CharSequence, android.graphics.Bitmap, float, android.content.IntentSender);
+    ctor public ChooserTarget(java.lang.CharSequence, android.graphics.drawable.Icon, float, android.app.PendingIntent);
+    ctor public ChooserTarget(java.lang.CharSequence, android.graphics.drawable.Icon, float, android.content.IntentSender);
     method public int describeContents();
-    method public android.graphics.Bitmap getIcon();
+    method public android.graphics.drawable.Icon getIcon();
     method public android.content.IntentSender getIntentSender();
     method public float getScore();
     method public java.lang.CharSequence getTitle();
diff --git a/api/system-current.txt b/api/system-current.txt
index bc47229..8cf81e9 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -30656,10 +30656,10 @@
 package android.service.chooser {
 
   public final class ChooserTarget implements android.os.Parcelable {
-    ctor public ChooserTarget(java.lang.CharSequence, android.graphics.Bitmap, float, android.app.PendingIntent);
-    ctor public ChooserTarget(java.lang.CharSequence, android.graphics.Bitmap, float, android.content.IntentSender);
+    ctor public ChooserTarget(java.lang.CharSequence, android.graphics.drawable.Icon, float, android.app.PendingIntent);
+    ctor public ChooserTarget(java.lang.CharSequence, android.graphics.drawable.Icon, float, android.content.IntentSender);
     method public int describeContents();
-    method public android.graphics.Bitmap getIcon();
+    method public android.graphics.drawable.Icon getIcon();
     method public android.content.IntentSender getIntentSender();
     method public float getScore();
     method public java.lang.CharSequence getTitle();
diff --git a/core/java/android/service/chooser/ChooserTarget.java b/core/java/android/service/chooser/ChooserTarget.java
index 4c94ee7..50c435a 100644
--- a/core/java/android/service/chooser/ChooserTarget.java
+++ b/core/java/android/service/chooser/ChooserTarget.java
@@ -25,6 +25,7 @@
 import android.content.IntentFilter;
 import android.content.IntentSender;
 import android.graphics.Bitmap;
+import android.graphics.drawable.Icon;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -34,6 +35,16 @@
 /**
  * A ChooserTarget represents a deep-link into an application as returned by a
  * {@link android.service.chooser.ChooserTargetService}.
+ *
+ * <p>A chooser target represents a specific deep link target into an application exposed
+ * for selection by the user. This might be a frequently emailed contact, a recently active
+ * group messaging conversation, a folder in a cloud storage app, a collection of related
+ * items published on a social media service or any other contextually relevant grouping
+ * of target app + relevant metadata.</p>
+ *
+ * <p>Creators of chooser targets should consult the relevant design guidelines for the type
+ * of target they are presenting. For example, targets involving people should be presented
+ * with a circular icon.</p>
  */
 public final class ChooserTarget implements Parcelable {
     private static final String TAG = "ChooserTarget";
@@ -48,7 +59,7 @@
      * The icon that will be shown to the user to represent this target.
      * The system may resize this icon as appropriate.
      */
-    private Bitmap mIcon;
+    private Icon mIcon;
 
     /**
      * The IntentSender that will be used to deliver the intent to the target.
@@ -93,7 +104,7 @@
      * @param score ranking score for this target between 0.0f and 1.0f, inclusive
      * @param pendingIntent PendingIntent to fill in and send if the user chooses this target
      */
-    public ChooserTarget(CharSequence title, Bitmap icon, float score,
+    public ChooserTarget(CharSequence title, Icon icon, float score,
             PendingIntent pendingIntent) {
         this(title, icon, score, pendingIntent.getIntentSender());
     }
@@ -129,7 +140,7 @@
      * @param score ranking score for this target between 0.0f and 1.0f, inclusive
      * @param intentSender IntentSender to fill in and send if the user chooses this target
      */
-    public ChooserTarget(CharSequence title, Bitmap icon, float score, IntentSender intentSender) {
+    public ChooserTarget(CharSequence title, Icon icon, float score, IntentSender intentSender) {
         mTitle = title;
         mIcon = icon;
         if (score > 1.f || score < 0.f) {
@@ -143,7 +154,7 @@
     ChooserTarget(Parcel in) {
         mTitle = in.readCharSequence();
         if (in.readInt() != 0) {
-            mIcon = Bitmap.CREATOR.createFromParcel(in);
+            mIcon = Icon.CREATOR.createFromParcel(in);
         } else {
             mIcon = null;
         }
@@ -167,7 +178,7 @@
      *
      * @return the icon representing this target, intended to be shown to a user
      */
-    public Bitmap getIcon() {
+    public Icon getIcon() {
         return mIcon;
     }
 
diff --git a/core/java/android/service/chooser/ChooserTargetService.java b/core/java/android/service/chooser/ChooserTargetService.java
index 699bd0a..0d1834a 100644
--- a/core/java/android/service/chooser/ChooserTargetService.java
+++ b/core/java/android/service/chooser/ChooserTargetService.java
@@ -107,7 +107,7 @@
      * <p>The returned list should be sorted such that the most relevant targets appear first.
      * Any PendingIntents used to construct the resulting ChooserTargets should always be prepared
      * to have the relevant data fields filled in by the sender. See
-     * {@link ChooserTarget#ChooserTarget(CharSequence, android.graphics.Bitmap, float, android.app.PendingIntent) ChooserTarget}.</p>
+     * {@link ChooserTarget#ChooserTarget(CharSequence, android.graphics.drawable.Icon, float, android.app.PendingIntent) ChooserTarget}.</p>
      *
      * <p><em>Important:</em> Calls to this method from other applications will occur on
      * a binder thread, not on your app's main thread. Make sure that access to relevant data
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 83fa967..ea18c12 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -29,8 +29,8 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
 import android.database.DataSetObserver;
-import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -51,10 +51,8 @@
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
 import android.widget.AbsListView;
 import android.widget.BaseAdapter;
-import android.widget.LinearLayout;
 import android.widget.ListView;
 import com.android.internal.R;
 
@@ -74,6 +72,8 @@
     private IntentSender mRefinementIntentSender;
     private RefinementResultReceiver mRefinementResultReceiver;
 
+    private Intent mReferrerFillInIntent;
+
     private ChooserListAdapter mChooserListAdapter;
 
     private final List<ChooserTargetServiceConnection> mServiceConnections = new ArrayList<>();
@@ -81,7 +81,7 @@
     private static final int CHOOSER_TARGET_SERVICE_RESULT = 1;
     private static final int CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT = 2;
 
-    private Handler mTargetResultHandler = new Handler() {
+    private final Handler mChooserHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
@@ -176,6 +176,8 @@
             }
         }
 
+        mReferrerFillInIntent = new Intent().putExtra(Intent.EXTRA_REFERRER, getReferrer());
+
         mChosenComponentSender = intent.getParcelableExtra(
                 Intent.EXTRA_CHOSEN_COMPONENT_INTENT_SENDER);
         mRefinementIntentSender = intent.getParcelableExtra(
@@ -346,7 +348,7 @@
         if (!mServiceConnections.isEmpty()) {
             if (DEBUG) Log.d(TAG, "queryTargets setting watchdog timer for "
                     + WATCHDOG_TIMEOUT_MILLIS + "ms");
-            mTargetResultHandler.sendEmptyMessageDelayed(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT,
+            mChooserHandler.sendEmptyMessageDelayed(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT,
                     WATCHDOG_TIMEOUT_MILLIS);
         }
     }
@@ -379,7 +381,7 @@
             unbindService(conn);
         }
         mServiceConnections.clear();
-        mTargetResultHandler.removeMessages(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT);
+        mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT);
     }
 
     void onRefinementResult(TargetInfo selectedTarget, Intent matchingIntent) {
@@ -435,7 +437,7 @@
         private final ResolveInfo mBackupResolveInfo;
         private final ChooserTarget mChooserTarget;
         private Drawable mBadgeIcon = null;
-        private final Drawable mDisplayIcon;
+        private Drawable mDisplayIcon;
         private final Intent mFillInIntent;
         private final int mFillInFlags;
 
@@ -451,7 +453,9 @@
                     }
                 }
             }
-            mDisplayIcon = new BitmapDrawable(getResources(), chooserTarget.getIcon());
+            final Icon icon = chooserTarget.getIcon();
+            // TODO do this in the background
+            mDisplayIcon = icon != null ? icon.loadDrawable(ChooserActivity.this) : null;
 
             if (sourceInfo != null) {
                 mBackupResolveInfo = null;
@@ -497,9 +501,12 @@
                     ? mSourceInfo.getResolvedIntent() : getTargetIntent();
             if (result == null) {
                 Log.e(TAG, "ChooserTargetInfo#getFillInIntent: no fillIn intent available");
-            } else if (mFillInIntent != null) {
+            } else {
                 result = new Intent(result);
-                result.fillIn(mFillInIntent, mFillInFlags);
+                if (mFillInIntent != null) {
+                    result.fillIn(mFillInIntent, mFillInFlags);
+                }
+                result.fillIn(mReferrerFillInIntent, 0);
             }
             return result;
         }
@@ -867,7 +874,7 @@
                 msg.what = CHOOSER_TARGET_SERVICE_RESULT;
                 msg.obj = new ServiceResultInfo(mOriginalTarget, targets,
                         ChooserTargetServiceConnection.this);
-                mTargetResultHandler.sendMessage(msg);
+                mChooserHandler.sendMessage(msg);
             }
         };