am cb29a8a1: am 2fca4812: am 9ba039bb: Merge "Update ChooserTarget constructor to take ComponentName, Bundle" into mnc-dev

* commit 'cb29a8a17a6634ad8b3010bfd4d47eca0f305d96':
  Update ChooserTarget constructor to take ComponentName, Bundle
This commit is contained in:
Adam Powell
2015-07-17 01:03:18 +00:00
committed by Android Git Automerger
6 changed files with 86 additions and 120 deletions

View File

@@ -28534,14 +28534,13 @@ package android.service.carrier {
package android.service.chooser {
public final class ChooserTarget implements android.os.Parcelable {
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);
ctor public ChooserTarget(java.lang.CharSequence, android.graphics.drawable.Icon, float, android.content.ComponentName, android.os.Bundle);
method public int describeContents();
method public android.content.ComponentName getComponentName();
method public android.graphics.drawable.Icon getIcon();
method public android.content.IntentSender getIntentSender();
method public android.os.Bundle getIntentExtras();
method public float getScore();
method public java.lang.CharSequence getTitle();
method public boolean sendIntent(android.content.Context, android.content.Intent);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.chooser.ChooserTarget> CREATOR;
}

View File

@@ -30594,14 +30594,13 @@ package android.service.carrier {
package android.service.chooser {
public final class ChooserTarget implements android.os.Parcelable {
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);
ctor public ChooserTarget(java.lang.CharSequence, android.graphics.drawable.Icon, float, android.content.ComponentName, android.os.Bundle);
method public int describeContents();
method public android.content.ComponentName getComponentName();
method public android.graphics.drawable.Icon getIcon();
method public android.content.IntentSender getIntentSender();
method public android.os.Bundle getIntentExtras();
method public float getScore();
method public java.lang.CharSequence getTitle();
method public boolean sendIntent(android.content.Context, android.content.Intent);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.chooser.ChooserTarget> CREATOR;
}

View File

@@ -17,20 +17,14 @@
package android.service.chooser;
import android.app.Activity;
import android.app.PendingIntent;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
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;
import android.os.UserHandle;
import android.util.Log;
/**
* A ChooserTarget represents a deep-link into an application as returned by a
@@ -62,11 +56,16 @@ public final class ChooserTarget implements Parcelable {
private Icon mIcon;
/**
* The IntentSender that will be used to deliver the intent to the target.
* It will be {@link android.content.Intent#fillIn(android.content.Intent, int)} filled in}
* by the real intent sent by the application.
* The ComponentName of the Activity to be invoked. Must be part of the target creator's
* own package or an Activity exported by its package.
*/
private IntentSender mIntentSender;
private ComponentName mComponentName;
/**
* A Bundle to merge with the extras of the intent sent to this target.
* Any extras here will override the extras from the original intent.
*/
private Bundle mIntentExtras;
/**
* The score given to this item. It can be normalized.
@@ -86,61 +85,23 @@ public final class ChooserTarget implements Parcelable {
* Scores should be in the range from 0.0f (unlikely match) to 1.0f (very relevant match).
* Scores for a set of targets do not need to sum to 1.</p>
*
* <p>Before being sent, the PendingIntent supplied will be
* {@link Intent#fillIn(Intent, int) filled in} by the Intent originally supplied
* to the chooser. When constructing a PendingIntent for use in a ChooserTarget, make sure
* that you permit the relevant fields to be filled in using the appropriate flags such as
* {@link Intent#FILL_IN_ACTION}, {@link Intent#FILL_IN_CATEGORIES},
* {@link Intent#FILL_IN_DATA} and {@link Intent#FILL_IN_CLIP_DATA}. Note that
* {@link Intent#FILL_IN_CLIP_DATA} is required to appropriately receive URI permission grants
* for {@link Intent#ACTION_SEND} intents.</p>
* <p>The ComponentName must be the name of an Activity component in the creator's own
* package, or an exported component from any other package. You may provide an optional
* Bundle of extras that will be merged into the final intent before it is sent to the
* target Activity; use this to add any additional data about the deep link that the target
* activity will read. e.g. conversation IDs, email addresses, etc.</p>
*
* <p>Take care not to place custom {@link android.os.Parcelable} types into
* the PendingIntent as extras, as the system will not be able to unparcel it to merge
* additional extras.</p>
* the extras bundle, as the system will not be able to unparcel them to merge them.</p>
*
* @param title title of this target that will be shown to a user
* @param icon icon to represent this target
* @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
* @param componentName Name of the component to be launched if this target is chosen
* @param intentExtras Bundle of extras to merge with the extras of the launched intent
*/
public ChooserTarget(CharSequence title, Icon icon, float score,
PendingIntent pendingIntent) {
this(title, icon, score, pendingIntent.getIntentSender());
}
/**
* Construct a deep link target for presentation by a chooser UI.
*
* <p>A target is composed of a title and an icon for presentation to the user.
* The UI presenting this target may truncate the title if it is too long to be presented
* in the available space, as well as crop, resize or overlay the supplied icon.</p>
*
* <p>The creator of a target may supply a ranking score. This score is assumed to be relative
* to the other targets supplied by the same
* {@link ChooserTargetService#onGetChooserTargets(ComponentName, IntentFilter) query}.
* Scores should be in the range from 0.0f (unlikely match) to 1.0f (very relevant match).
* Scores for a set of targets do not need to sum to 1.</p>
*
* <p>Before being sent, the IntentSender supplied will be
* {@link Intent#fillIn(Intent, int) filled in} by the Intent originally supplied
* to the chooser. When constructing an IntentSender for use in a ChooserTarget, make sure
* that you permit the relevant fields to be filled in using the appropriate flags such as
* {@link Intent#FILL_IN_ACTION}, {@link Intent#FILL_IN_CATEGORIES},
* {@link Intent#FILL_IN_DATA} and {@link Intent#FILL_IN_CLIP_DATA}. Note that
* {@link Intent#FILL_IN_CLIP_DATA} is required to appropriately receive URI permission grants
* for {@link Intent#ACTION_SEND} intents.</p>
*
* <p>Take care not to place custom {@link android.os.Parcelable} types into
* the IntentSender as extras, as the system will not be able to unparcel it to merge
* additional extras.</p>
*
* @param title title of this target that will be shown to a user
* @param icon icon to represent this target
* @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, Icon icon, float score, IntentSender intentSender) {
ComponentName componentName, @Nullable Bundle intentExtras) {
mTitle = title;
mIcon = icon;
if (score > 1.f || score < 0.f) {
@@ -148,7 +109,8 @@ public final class ChooserTarget implements Parcelable {
+ "must be between 0.0f and 1.0f");
}
mScore = score;
mIntentSender = intentSender;
mComponentName = componentName;
mIntentExtras = intentExtras;
}
ChooserTarget(Parcel in) {
@@ -159,7 +121,8 @@ public final class ChooserTarget implements Parcelable {
mIcon = null;
}
mScore = in.readFloat();
mIntentSender = IntentSender.readIntentSenderOrNullFromParcel(in);
mComponentName = ComponentName.readFromParcel(in);
mIntentExtras = in.readBundle();
}
/**
@@ -194,49 +157,29 @@ public final class ChooserTarget implements Parcelable {
}
/**
* Returns the raw IntentSender supplied by the ChooserTarget's creator.
* This may be null if the creator specified a regular Intent instead.
* Returns the ComponentName of the Activity that should be launched for this ChooserTarget.
*
* <p>To fill in and send the intent, see {@link #sendIntent(Context, Intent)}.</p>
*
* @return the IntentSender supplied by the ChooserTarget's creator
* @return the name of the target Activity to launch
*/
public IntentSender getIntentSender() {
return mIntentSender;
public ComponentName getComponentName() {
return mComponentName;
}
/**
* Fill in the IntentSender supplied by the ChooserTarget's creator and send it.
* Returns the Bundle of extras to be added to an intent launched to this target.
*
* @param context the sending Context; generally the Activity presenting the chooser UI
* @param fillInIntent the Intent provided to the Chooser to be sent to a selected target
* @return true if sending the Intent was successful
* @return the extras to merge with the extras of the intent being launched
*/
public boolean sendIntent(Context context, Intent fillInIntent) {
if (fillInIntent != null) {
fillInIntent.migrateExtraStreamToClipData();
fillInIntent.prepareToLeaveProcess();
}
if (mIntentSender != null) {
try {
mIntentSender.sendIntent(context, 0, fillInIntent, null, null);
return true;
} catch (IntentSender.SendIntentException e) {
Log.e(TAG, "sendIntent " + this + " failed", e);
return false;
}
} else {
Log.e(TAG, "sendIntent " + this + " failed - no IntentSender to send");
return false;
}
public Bundle getIntentExtras() {
return mIntentExtras;
}
@Override
public String toString() {
return "ChooserTarget{"
+ (mIntentSender != null ? mIntentSender.getCreatorPackage() : null)
+ ", "
+ "'" + mTitle
+ mComponentName
+ ", " + mIntentExtras
+ ", '" + mTitle
+ "', " + mScore + "}";
}
@@ -255,7 +198,8 @@ public final class ChooserTarget implements Parcelable {
dest.writeInt(0);
}
dest.writeFloat(mScore);
IntentSender.writeIntentSenderOrNullToParcel(mIntentSender, dest);
ComponentName.writeToParcel(mComponentName, dest);
dest.writeBundle(mIntentExtras);
}
public static final Creator<ChooserTarget> CREATOR

View File

@@ -105,9 +105,8 @@ public abstract class ChooserTargetService extends Service {
* can handle an intent.
*
* <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.drawable.Icon, float, android.app.PendingIntent) ChooserTarget}.</p>
* The score for each ChooserTarget will be combined with the system's score for the original
* target Activity to sort and filter targets presented to the user.</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

View File

@@ -21,7 +21,7 @@ import android.service.chooser.ChooserTarget;
/**
* @hide
*/
interface IChooserTargetResult
oneway interface IChooserTargetResult
{
void sendResult(in List<ChooserTarget> targets);
}

View File

@@ -471,6 +471,36 @@ public class ChooserActivity extends ResolverActivity {
return false;
}
void filterServiceTargets(String packageName, List<ChooserTarget> targets) {
if (targets == null) {
return;
}
final PackageManager pm = getPackageManager();
for (int i = targets.size() - 1; i >= 0; i--) {
final ChooserTarget target = targets.get(i);
final ComponentName targetName = target.getComponentName();
if (packageName != null && packageName.equals(targetName.getPackageName())) {
// Anything from the original target's package is fine.
continue;
}
boolean remove;
try {
final ActivityInfo ai = pm.getActivityInfo(targetName, 0);
remove = !ai.exported || ai.permission != null;
} catch (NameNotFoundException e) {
Log.e(TAG, "Target " + target + " returned by " + packageName
+ " component not found");
remove = true;
}
if (remove) {
targets.remove(i);
}
}
}
@Override
ResolveListAdapter createAdapter(Context context, List<Intent> payloadIntents,
Intent[] initialIntents, List<ResolveInfo> rList, int launchedFromUid,
@@ -554,11 +584,11 @@ public class ChooserActivity extends ResolverActivity {
return null;
}
private Intent getFillInIntent() {
private Intent getBaseIntentToSend() {
Intent result = mSourceInfo != null
? mSourceInfo.getResolvedIntent() : getTargetIntent();
if (result == null) {
Log.e(TAG, "ChooserTargetInfo#getFillInIntent: no fillIn intent available");
Log.e(TAG, "ChooserTargetInfo: no base intent available to send");
} else {
result = new Intent(result);
if (mFillInIntent != null) {
@@ -571,31 +601,24 @@ public class ChooserActivity extends ResolverActivity {
@Override
public boolean start(Activity activity, Bundle options) {
final Intent intent = getFillInIntent();
if (intent == null) {
return false;
}
return mChooserTarget.sendIntent(activity, intent);
throw new RuntimeException("ChooserTargets should be started as caller.");
}
@Override
public boolean startAsCaller(Activity activity, Bundle options, int userId) {
final Intent intent = getFillInIntent();
final Intent intent = getBaseIntentToSend();
if (intent == null) {
return false;
}
// ChooserTargets will launch with their IntentSender's identity
return mChooserTarget.sendIntent(activity, intent);
intent.setComponent(mChooserTarget.getComponentName());
intent.putExtras(mChooserTarget.getIntentExtras());
activity.startActivityAsCaller(intent, options, true, userId);
return true;
}
@Override
public boolean startAsUser(Activity activity, Bundle options, UserHandle user) {
final Intent intent = getFillInIntent();
if (intent == null) {
return false;
}
// ChooserTargets will launch with their IntentSender's identity
return mChooserTarget.sendIntent(activity, intent);
throw new RuntimeException("ChooserTargets should be started as caller.");
}
@Override
@@ -998,6 +1021,8 @@ public class ChooserActivity extends ResolverActivity {
private final IChooserTargetResult mChooserTargetResult = new IChooserTargetResult.Stub() {
@Override
public void sendResult(List<ChooserTarget> targets) throws RemoteException {
filterServiceTargets(mOriginalTarget.getResolveInfo().activityInfo.packageName,
targets);
final Message msg = Message.obtain();
msg.what = CHOOSER_TARGET_SERVICE_RESULT;
msg.obj = new ServiceResultInfo(mOriginalTarget, targets,