summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt3
-rw-r--r--api/system-current.txt3
-rw-r--r--core/java/android/content/Intent.java8
-rw-r--r--core/java/android/service/chooser/ChooserTarget.java149
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java298
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java239
-rw-r--r--core/res/res/layout/chooser_grid.xml20
-rw-r--r--core/res/res/layout/chooser_row.xml31
-rw-r--r--core/res/res/layout/resolve_grid_item.xml33
-rw-r--r--core/res/res/values/colors.xml2
-rwxr-xr-xcore/res/res/values/symbols.xml4
11 files changed, 467 insertions, 323 deletions
diff --git a/api/current.txt b/api/current.txt
index ef2c4dae5209..6c9dd35c95f2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -8294,7 +8294,6 @@ package android.content {
field public static final java.lang.String EXTRA_CHANGED_PACKAGE_LIST = "android.intent.extra.changed_package_list";
field public static final java.lang.String EXTRA_CHANGED_UID_LIST = "android.intent.extra.changed_uid_list";
field public static final java.lang.String EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER = "android.intent.extra.CHOOSER_REFINEMENT_INTENT_SENDER";
- field public static final java.lang.String EXTRA_CHOOSER_TARGETS = "android.intent.extra.CHOOSER_TARGETS";
field public static final java.lang.String EXTRA_CHOSEN_COMPONENT = "android.intent.extra.CHOSEN_COMPONENT";
field public static final java.lang.String EXTRA_CHOSEN_COMPONENT_INTENT_SENDER = "android.intent.extra.CHOSEN_COMPONENT_INTENT_SENDER";
field public static final java.lang.String EXTRA_DATA_REMOVED = "android.intent.extra.DATA_REMOVED";
@@ -28730,10 +28729,8 @@ 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.Bitmap, float, android.content.Intent);
method public int describeContents();
method public android.graphics.Bitmap getIcon();
- method public android.content.Intent getIntent();
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 4508b20e3810..6b1f809ad47b 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -8520,7 +8520,6 @@ package android.content {
field public static final java.lang.String EXTRA_CHANGED_PACKAGE_LIST = "android.intent.extra.changed_package_list";
field public static final java.lang.String EXTRA_CHANGED_UID_LIST = "android.intent.extra.changed_uid_list";
field public static final java.lang.String EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER = "android.intent.extra.CHOOSER_REFINEMENT_INTENT_SENDER";
- field public static final java.lang.String EXTRA_CHOOSER_TARGETS = "android.intent.extra.CHOOSER_TARGETS";
field public static final java.lang.String EXTRA_CHOSEN_COMPONENT = "android.intent.extra.CHOSEN_COMPONENT";
field public static final java.lang.String EXTRA_CHOSEN_COMPONENT_INTENT_SENDER = "android.intent.extra.CHOSEN_COMPONENT_INTENT_SENDER";
field public static final java.lang.String EXTRA_DATA_REMOVED = "android.intent.extra.DATA_REMOVED";
@@ -30744,10 +30743,8 @@ 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.Bitmap, float, android.content.Intent);
method public int describeContents();
method public android.graphics.Bitmap getIcon();
- method public android.content.Intent getIntent();
method public android.content.IntentSender getIntentSender();
method public float getScore();
method public java.lang.CharSequence getTitle();
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 6f543a80564a..7d767602541a 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3365,14 +3365,6 @@ public class Intent implements Parcelable, Cloneable {
public static final String EXTRA_INITIAL_INTENTS = "android.intent.extra.INITIAL_INTENTS";
/**
- * A Parcelable[] of {@link android.service.chooser.ChooserTarget ChooserTarget} objects
- * as set with {@link #putExtra(String, Parcelable[])} representing additional app-specific
- * targets to place at the front of the list of choices. Shown to the user with
- * {@link #ACTION_CHOOSER}.
- */
- public static final String EXTRA_CHOOSER_TARGETS = "android.intent.extra.CHOOSER_TARGETS";
-
- /**
* A Bundle forming a mapping of potential target package names to different extras Bundles
* to add to the default intent extras in {@link #EXTRA_INTENT} when used with
* {@link #ACTION_CHOOSER}. Each key should be a package name. The package need not
diff --git a/core/java/android/service/chooser/ChooserTarget.java b/core/java/android/service/chooser/ChooserTarget.java
index f0ca276f11f2..4c94ee7ca23c 100644
--- a/core/java/android/service/chooser/ChooserTarget.java
+++ b/core/java/android/service/chooser/ChooserTarget.java
@@ -58,12 +58,6 @@ public final class ChooserTarget implements Parcelable {
private IntentSender mIntentSender;
/**
- * A raw intent provided in lieu of an IntentSender. Will be filled in and sent
- * by {@link #sendIntent(Context, Intent)}.
- */
- private Intent mIntent;
-
- /**
* The score given to this item. It can be normalized.
*/
private float mScore;
@@ -146,43 +140,6 @@ public final class ChooserTarget implements Parcelable {
mIntentSender = intentSender;
}
- /**
- * 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 Intent supplied will be
- * {@link Intent#fillIn(Intent, int) filled in} by the Intent originally supplied
- * to the chooser.</p>
- *
- * <p>Take care not to place custom {@link android.os.Parcelable} types into
- * the Intent 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 intent Intent to fill in and send if the user chooses this target
- */
- public ChooserTarget(CharSequence title, Bitmap icon, float score, Intent intent) {
- mTitle = title;
- mIcon = icon;
- if (score > 1.f || score < 0.f) {
- throw new IllegalArgumentException("Score " + score + " out of range; "
- + "must be between 0.0f and 1.0f");
- }
- mScore = score;
- mIntent = intent;
- }
-
ChooserTarget(Parcel in) {
mTitle = in.readCharSequence();
if (in.readInt() != 0) {
@@ -192,9 +149,6 @@ public final class ChooserTarget implements Parcelable {
}
mScore = in.readFloat();
mIntentSender = IntentSender.readIntentSenderOrNullFromParcel(in);
- if (in.readInt() != 0) {
- mIntent = Intent.CREATOR.createFromParcel(in);
- }
}
/**
@@ -241,18 +195,6 @@ public final class ChooserTarget implements Parcelable {
}
/**
- * Returns the Intent supplied by the ChooserTarget's creator.
- * This may be null if the creator specified an IntentSender or PendingIntent instead.
- *
- * <p>To fill in and send the intent, see {@link #sendIntent(Context, Intent)}.</p>
- *
- * @return the Intent supplied by the ChooserTarget's creator
- */
- public Intent getIntent() {
- return mIntent;
- }
-
- /**
* Fill in the IntentSender supplied by the ChooserTarget's creator and send it.
*
* @param context the sending Context; generally the Activity presenting the chooser UI
@@ -272,91 +214,8 @@ public final class ChooserTarget implements Parcelable {
Log.e(TAG, "sendIntent " + this + " failed", e);
return false;
}
- } else if (mIntent != null) {
- try {
- final Intent toSend = new Intent(mIntent);
- toSend.fillIn(fillInIntent, 0);
- context.startActivity(toSend);
- return true;
- } catch (Exception e) {
- Log.e(TAG, "sendIntent " + this + " failed", e);
- return false;
- }
} else {
- Log.e(TAG, "sendIntent " + this + " failed - no IntentSender or Intent to send");
- return false;
- }
- }
-
- /**
- * Same as {@link #sendIntent(Context, Intent)}, but offers a userId field to use
- * for launching the {@link #getIntent() intent} using
- * {@link Activity#startActivityAsCaller(Intent, Bundle, int)} if the
- * {@link #getIntentSender() IntentSender} is not present. If the IntentSender is present,
- * it will be invoked as usual with its own calling identity.
- *
- * @hide internal use only.
- */
- public boolean sendIntentAsCaller(Activity context, Intent fillInIntent, int userId) {
- 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 if (mIntent != null) {
- try {
- final Intent toSend = new Intent(mIntent);
- toSend.fillIn(fillInIntent, 0);
- context.startActivityAsCaller(toSend, null, userId);
- return true;
- } catch (Exception e) {
- Log.e(TAG, "sendIntent " + this + " failed", e);
- return false;
- }
- } else {
- Log.e(TAG, "sendIntent " + this + " failed - no IntentSender or Intent to send");
- return false;
- }
- }
-
- /**
- * The UserHandle is only used if we're launching a raw intent. The IntentSender will be
- * launched with its associated identity.
- *
- * @hide Internal use only
- */
- public boolean sendIntentAsUser(Activity context, Intent fillInIntent, UserHandle user) {
- 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 if (mIntent != null) {
- try {
- final Intent toSend = new Intent(mIntent);
- toSend.fillIn(fillInIntent, 0);
- context.startActivityAsUser(toSend, user);
- return true;
- } catch (Exception e) {
- Log.e(TAG, "sendIntent " + this + " failed", e);
- return false;
- }
- } else {
- Log.e(TAG, "sendIntent " + this + " failed - no IntentSender or Intent to send");
+ Log.e(TAG, "sendIntent " + this + " failed - no IntentSender to send");
return false;
}
}
@@ -364,7 +223,7 @@ public final class ChooserTarget implements Parcelable {
@Override
public String toString() {
return "ChooserTarget{"
- + (mIntentSender != null ? mIntentSender.getCreatorPackage() : mIntent)
+ + (mIntentSender != null ? mIntentSender.getCreatorPackage() : null)
+ ", "
+ "'" + mTitle
+ "', " + mScore + "}";
@@ -386,10 +245,6 @@ public final class ChooserTarget implements Parcelable {
}
dest.writeFloat(mScore);
IntentSender.writeIntentSenderOrNullToParcel(mIntentSender, dest);
- dest.writeInt(mIntent != null ? 1 : 0);
- if (mIntent != null) {
- mIntent.writeToParcel(dest, 0);
- }
}
public static final Creator<ChooserTarget> CREATOR
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 62ca1f0f3935..83fa967e5ca8 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -24,9 +24,11 @@ import android.content.IntentSender;
import android.content.IntentSender.SendIntentException;
import android.content.ServiceConnection;
import android.content.pm.ActivityInfo;
+import android.content.pm.LabeledIntent;
import android.content.pm.PackageManager;
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.os.Bundle;
@@ -37,6 +39,7 @@ import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.UserHandle;
+import android.os.UserManager;
import android.service.chooser.ChooserTarget;
import android.service.chooser.ChooserTargetService;
import android.service.chooser.IChooserTargetResult;
@@ -44,8 +47,16 @@ import android.service.chooser.IChooserTargetService;
import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;
+import android.view.LayoutInflater;
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;
import java.util.ArrayList;
import java.util.List;
@@ -63,7 +74,7 @@ public class ChooserActivity extends ResolverActivity {
private IntentSender mRefinementIntentSender;
private RefinementResultReceiver mRefinementResultReceiver;
- private ChooserTarget[] mCallerChooserTargets;
+ private ChooserListAdapter mChooserListAdapter;
private final List<ChooserTargetServiceConnection> mServiceConnections = new ArrayList<>();
@@ -84,8 +95,7 @@ public class ChooserActivity extends ResolverActivity {
+ " Have you considered returning results faster?");
break;
}
- final ChooserListAdapter cla = (ChooserListAdapter) getAdapter();
- cla.addServiceResults(sri.originalTarget, sri.resultTargets);
+ mChooserListAdapter.addServiceResults(sri.originalTarget, sri.resultTargets);
unbindService(sri.connection);
mServiceConnections.remove(sri.connection);
break;
@@ -166,20 +176,6 @@ public class ChooserActivity extends ResolverActivity {
}
}
- pa = intent.getParcelableArrayExtra(Intent.EXTRA_CHOOSER_TARGETS);
- if (pa != null) {
- final ChooserTarget[] targets = new ChooserTarget[pa.length];
- for (int i = 0; i < pa.length; i++) {
- if (!(pa[i] instanceof ChooserTarget)) {
- Log.w(TAG, "Chooser target #" + i + " is not a ChooserTarget: " + pa[i]);
- finish();
- super.onCreate(null);
- return;
- }
- targets[i] = (ChooserTarget) pa[i];
- }
- mCallerChooserTargets = targets;
- }
mChosenComponentSender = intent.getParcelableExtra(
Intent.EXTRA_CHOSEN_COMPONENT_INTENT_SENDER);
mRefinementIntentSender = intent.getParcelableExtra(
@@ -233,8 +229,19 @@ public class ChooserActivity extends ResolverActivity {
}
@Override
+ void onPrepareAdapterView(AbsListView adapterView, ResolveListAdapter adapter,
+ boolean alwaysUseOption) {
+ final ListView listView = adapterView instanceof ListView ? (ListView) adapterView : null;
+ mChooserListAdapter = (ChooserListAdapter) adapter;
+ adapterView.setAdapter(new ChooserRowAdapter(mChooserListAdapter));
+ if (listView != null) {
+ listView.setItemsCanFocus(true);
+ }
+ }
+
+ @Override
int getLayoutResource() {
- return com.android.internal.R.layout.chooser_grid;
+ return R.layout.chooser_grid;
}
@Override
@@ -413,10 +420,11 @@ public class ChooserActivity extends ResolverActivity {
}
@Override
- ResolveListAdapter createAdapter(Context context, Intent[] initialIntents,
- List<ResolveInfo> rList, int launchedFromUid, boolean filterLastUsed) {
- final ChooserListAdapter adapter = new ChooserListAdapter(context, initialIntents, rList,
- launchedFromUid, filterLastUsed, mCallerChooserTargets);
+ ResolveListAdapter createAdapter(Context context, List<Intent> payloadIntents,
+ Intent[] initialIntents, List<ResolveInfo> rList, int launchedFromUid,
+ boolean filterLastUsed) {
+ final ChooserListAdapter adapter = new ChooserListAdapter(context, payloadIntents,
+ initialIntents, rList, launchedFromUid, filterLastUsed);
if (DEBUG) Log.d(TAG, "Adapter created; querying services");
queryTargetServices(adapter);
return adapter;
@@ -426,17 +434,23 @@ public class ChooserActivity extends ResolverActivity {
private final DisplayResolveInfo mSourceInfo;
private final ResolveInfo mBackupResolveInfo;
private final ChooserTarget mChooserTarget;
+ private Drawable mBadgeIcon = null;
private final Drawable mDisplayIcon;
private final Intent mFillInIntent;
private final int mFillInFlags;
- public ChooserTargetInfo(ChooserTarget target) {
- this(null, target);
- }
-
public ChooserTargetInfo(DisplayResolveInfo sourceInfo, ChooserTarget chooserTarget) {
mSourceInfo = sourceInfo;
mChooserTarget = chooserTarget;
+ if (sourceInfo != null) {
+ final ResolveInfo ri = sourceInfo.getResolveInfo();
+ if (ri != null) {
+ final ActivityInfo ai = ri.activityInfo;
+ if (ai != null && ai.applicationInfo != null) {
+ mBadgeIcon = getPackageManager().getApplicationIcon(ai.applicationInfo);
+ }
+ }
+ }
mDisplayIcon = new BitmapDrawable(getResources(), chooserTarget.getIcon());
if (sourceInfo != null) {
@@ -453,6 +467,7 @@ public class ChooserActivity extends ResolverActivity {
mSourceInfo = other.mSourceInfo;
mBackupResolveInfo = other.mBackupResolveInfo;
mChooserTarget = other.mChooserTarget;
+ mBadgeIcon = other.mBadgeIcon;
mDisplayIcon = other.mDisplayIcon;
mFillInIntent = fillInIntent;
mFillInFlags = flags;
@@ -460,10 +475,7 @@ public class ChooserActivity extends ResolverActivity {
@Override
public Intent getResolvedIntent() {
- final Intent targetIntent = mChooserTarget.getIntent();
- if (targetIntent != null) {
- return targetIntent;
- } else if (mSourceInfo != null) {
+ if (mSourceInfo != null) {
return mSourceInfo.getResolvedIntent();
}
return getTargetIntent();
@@ -507,7 +519,8 @@ public class ChooserActivity extends ResolverActivity {
if (intent == null) {
return false;
}
- return mChooserTarget.sendIntentAsCaller(activity, intent, userId);
+ // ChooserTargets will launch with their IntentSender's identity
+ return mChooserTarget.sendIntent(activity, intent);
}
@Override
@@ -516,7 +529,8 @@ public class ChooserActivity extends ResolverActivity {
if (intent == null) {
return false;
}
- return mChooserTarget.sendIntentAsUser(activity, intent, user);
+ // ChooserTargets will launch with their IntentSender's identity
+ return mChooserTarget.sendIntent(activity, intent);
}
@Override
@@ -540,6 +554,11 @@ public class ChooserActivity extends ResolverActivity {
}
@Override
+ public Drawable getBadgeIcon() {
+ return mBadgeIcon;
+ }
+
+ @Override
public TargetInfo cloneFilledIn(Intent fillInIntent, int flags) {
return new ChooserTargetInfo(this, fillInIntent, flags);
}
@@ -556,16 +575,49 @@ public class ChooserActivity extends ResolverActivity {
}
public class ChooserListAdapter extends ResolveListAdapter {
- private final List<ChooserTargetInfo> mServiceTargets = new ArrayList<>();
- private final List<ChooserTargetInfo> mCallerTargets = new ArrayList<>();
-
- public ChooserListAdapter(Context context, Intent[] initialIntents, List<ResolveInfo> rList,
- int launchedFromUid, boolean filterLastUsed, ChooserTarget[] callerChooserTargets) {
- super(context, initialIntents, rList, launchedFromUid, filterLastUsed);
+ public static final int TARGET_BAD = -1;
+ public static final int TARGET_CALLER = 0;
+ public static final int TARGET_SERVICE = 1;
+ public static final int TARGET_STANDARD = 2;
- if (callerChooserTargets != null) {
- for (ChooserTarget target : callerChooserTargets) {
- mCallerTargets.add(new ChooserTargetInfo(target));
+ private final List<ChooserTargetInfo> mServiceTargets = new ArrayList<>();
+ private final List<TargetInfo> mCallerTargets = new ArrayList<>();
+
+ public ChooserListAdapter(Context context, List<Intent> payloadIntents,
+ Intent[] initialIntents, List<ResolveInfo> rList, int launchedFromUid,
+ boolean filterLastUsed) {
+ // Don't send the initial intents through the shared ResolverActivity path,
+ // we want to separate them into a different section.
+ super(context, payloadIntents, null, rList, launchedFromUid, filterLastUsed);
+
+ if (initialIntents != null) {
+ final PackageManager pm = getPackageManager();
+ for (int i = 0; i < initialIntents.length; i++) {
+ final Intent ii = initialIntents[i];
+ if (ii == null) {
+ continue;
+ }
+ final ActivityInfo ai = ii.resolveActivityInfo(pm, 0);
+ if (ai == null) {
+ Log.w(TAG, "No activity found for " + ii);
+ continue;
+ }
+ ResolveInfo ri = new ResolveInfo();
+ ri.activityInfo = ai;
+ UserManager userManager =
+ (UserManager) getSystemService(Context.USER_SERVICE);
+ if (userManager.isManagedProfile()) {
+ ri.noResourceId = true;
+ }
+ if (ii instanceof LabeledIntent) {
+ LabeledIntent li = (LabeledIntent)ii;
+ ri.resolvePackageName = li.getSourcePackage();
+ ri.labelRes = li.getLabelResource();
+ ri.nonLocalizedLabel = li.getNonLocalizedLabel();
+ ri.icon = li.getIconResource();
+ }
+ mCallerTargets.add(new DisplayResolveInfo(ii, ri,
+ ri.loadLabel(pm), null, ii));
}
}
}
@@ -578,7 +630,7 @@ public class ChooserActivity extends ResolverActivity {
}
@Override
- public View createView(ViewGroup parent) {
+ public View onCreateView(ViewGroup parent) {
return mInflater.inflate(
com.android.internal.R.layout.resolve_grid_item, parent, false);
}
@@ -600,6 +652,41 @@ public class ChooserActivity extends ResolverActivity {
return super.getCount() + mServiceTargets.size() + mCallerTargets.size();
}
+ public int getCallerTargetsCount() {
+ return mCallerTargets.size();
+ }
+
+ public int getServiceTargetsCount() {
+ return mServiceTargets.size();
+ }
+
+ public int getStandardTargetCount() {
+ return super.getCount();
+ }
+
+ public int getPositionTargetType(int position) {
+ int offset = 0;
+
+ final int callerTargetCount = mCallerTargets.size();
+ if (position < callerTargetCount) {
+ return TARGET_CALLER;
+ }
+ offset += callerTargetCount;
+
+ final int serviceTargetCount = mServiceTargets.size();
+ if (position - offset < serviceTargetCount) {
+ return TARGET_SERVICE;
+ }
+ offset += serviceTargetCount;
+
+ final int standardTargetCount = super.getCount();
+ if (position - offset < standardTargetCount) {
+ return TARGET_STANDARD;
+ }
+
+ return TARGET_BAD;
+ }
+
@Override
public TargetInfo getItem(int position) {
int offset = 0;
@@ -643,6 +730,133 @@ public class ChooserActivity extends ResolverActivity {
}
}
+ class ChooserRowAdapter extends BaseAdapter {
+ private ChooserListAdapter mChooserListAdapter;
+ private final LayoutInflater mLayoutInflater;
+ private final int mColumnCount = 4;
+
+ public ChooserRowAdapter(ChooserListAdapter wrappedAdapter) {
+ mChooserListAdapter = wrappedAdapter;
+ mLayoutInflater = LayoutInflater.from(ChooserActivity.this);
+
+ wrappedAdapter.registerDataSetObserver(new DataSetObserver() {
+ @Override
+ public void onChanged() {
+ super.onChanged();
+ notifyDataSetChanged();
+ }
+
+ @Override
+ public void onInvalidated() {
+ super.onInvalidated();
+ notifyDataSetInvalidated();
+ }
+ });
+ }
+
+ @Override
+ public int getCount() {
+ return (int) (
+ Math.ceil((float) mChooserListAdapter.getCallerTargetsCount() / mColumnCount)
+ + Math.ceil((float) mChooserListAdapter.getServiceTargetsCount() / mColumnCount)
+ + Math.ceil((float) mChooserListAdapter.getStandardTargetCount() / mColumnCount)
+ );
+ }
+
+ @Override
+ public Object getItem(int position) {
+ // We have nothing useful to return here.
+ return position;
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ final View[] holder;
+ if (convertView == null) {
+ holder = createViewHolder(parent);
+ } else {
+ holder = (View[]) convertView.getTag();
+ }
+ bindViewHolder(position, holder);
+
+ // We keep the actual list item view as the last item in the holder array
+ return holder[mColumnCount];
+ }
+
+ View[] createViewHolder(ViewGroup parent) {
+ final View[] holder = new View[mColumnCount + 1];
+
+ final ViewGroup row = (ViewGroup) mLayoutInflater.inflate(R.layout.chooser_row,
+ parent, false);
+ for (int i = 0; i < mColumnCount; i++) {
+ holder[i] = mChooserListAdapter.createView(row);
+ row.addView(holder[i]);
+ }
+ row.setTag(holder);
+ holder[mColumnCount] = row;
+ return holder;
+ }
+
+ void bindViewHolder(int rowPosition, View[] holder) {
+ final int start = getFirstRowPosition(rowPosition);
+ final int startType = mChooserListAdapter.getPositionTargetType(start);
+
+ int end = start + mColumnCount - 1;
+ while (mChooserListAdapter.getPositionTargetType(end) != startType && end >= start) {
+ end--;
+ }
+
+ final ViewGroup row = (ViewGroup) holder[mColumnCount];
+
+ if (startType == ChooserListAdapter.TARGET_SERVICE) {
+ row.setBackgroundColor(getColor(R.color.chooser_service_row_background_color));
+ } else {
+ row.setBackground(null);
+ }
+
+ for (int i = 0; i < mColumnCount; i++) {
+ final View v = holder[i];
+ if (start + i <= end) {
+ v.setVisibility(View.VISIBLE);
+ final int itemIndex = start + i;
+ mChooserListAdapter.bindView(itemIndex, v);
+ v.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ startSelected(itemIndex, false, true);
+ }
+ });
+ } else {
+ v.setVisibility(View.GONE);
+ }
+ }
+ }
+
+ int getFirstRowPosition(int row) {
+ final int callerCount = mChooserListAdapter.getCallerTargetsCount();
+ final int callerRows = (int) Math.ceil((float) callerCount / mColumnCount);
+
+ if (row < callerRows) {
+ return row * mColumnCount;
+ }
+
+ final int serviceCount = mChooserListAdapter.getServiceTargetsCount();
+ final int serviceRows = (int) Math.ceil((float) serviceCount / mColumnCount);
+
+ if (row < callerRows + serviceRows) {
+ return callerCount + (row - callerRows) * mColumnCount;
+ }
+
+ return callerCount + serviceCount
+ + (row - callerRows - serviceRows) * mColumnCount;
+ }
+ }
+
class ChooserTargetServiceConnection implements ServiceConnection {
private final DisplayResolveInfo mOriginalTarget;
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 204866432000..26cdf6b6eaa2 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -25,7 +25,6 @@ import android.provider.Settings;
import android.text.TextUtils;
import android.util.Slog;
import android.widget.AbsListView;
-import android.widget.GridView;
import com.android.internal.R;
import com.android.internal.content.PackageMonitor;
@@ -83,7 +82,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
* which there is more than one matching activity, allowing the user to decide
* which to go to. It is not normally used directly by application developers.
*/
-public class ResolverActivity extends Activity implements AdapterView.OnItemClickListener {
+public class ResolverActivity extends Activity {
private static final String TAG = "ResolverActivity";
private static final boolean DEBUG = false;
@@ -93,8 +92,6 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
private boolean mSafeForwardingMode;
private boolean mAlwaysUseOption;
private AbsListView mAdapterView;
- private ListView mListView;
- private GridView mGridView;
private Button mAlwaysButton;
private Button mOnceButton;
private View mProfileView;
@@ -217,6 +214,13 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
} catch (RemoteException e) {
mLaunchedFromUid = -1;
}
+
+ if (mLaunchedFromUid < 0 || UserHandle.isIsolated(mLaunchedFromUid)) {
+ // Gulp!
+ finish();
+ return;
+ }
+
mPm = getPackageManager();
mUsm = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
@@ -229,67 +233,11 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
final ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
mIconDpi = am.getLauncherLargeIconDensity();
+ // Add our initial intent as the first item, regardless of what else has already been added.
mIntents.add(0, new Intent(intent));
- mAdapter = createAdapter(this, initialIntents, rList, mLaunchedFromUid, alwaysUseOption);
-
- final int layoutId;
- final boolean useHeader;
- if (mAdapter.hasFilteredItem()) {
- layoutId = R.layout.resolver_list_with_default;
- alwaysUseOption = false;
- useHeader = true;
- } else {
- useHeader = false;
- layoutId = getLayoutResource();
- }
- mAlwaysUseOption = alwaysUseOption;
-
- if (mLaunchedFromUid < 0 || UserHandle.isIsolated(mLaunchedFromUid)) {
- // Gulp!
- finish();
- return;
- }
-
- int count = mAdapter.mDisplayList.size();
- if (count > 1 || (count == 1 && mAdapter.getOtherProfile() != null)) {
- setContentView(layoutId);
- mAdapterView = (AbsListView) findViewById(R.id.resolver_list);
- mAdapterView.setAdapter(mAdapter);
- mAdapterView.setOnItemClickListener(this);
- mAdapterView.setOnItemLongClickListener(new ItemLongClickListener());
-
- // Initialize the different types of collection views we may have. Depending
- // on which ones are initialized later we'll configure different properties.
- if (mAdapterView instanceof ListView) {
- mListView = (ListView) mAdapterView;
- }
- if (mAdapterView instanceof GridView) {
- mGridView = (GridView) mAdapterView;
- }
-
- if (alwaysUseOption) {
- mAdapterView.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
- }
- if (useHeader && mListView != null) {
- mListView.addHeaderView(LayoutInflater.from(this).inflate(
- R.layout.resolver_different_item_header, mListView, false));
- }
- } else if (count == 1) {
- safelyStartActivity(mAdapter.targetInfoForPosition(0, false));
- mPackageMonitor.unregister();
- mRegistered = false;
- finish();
- return;
- } else {
- setContentView(R.layout.resolver_list);
-
- final TextView empty = (TextView) findViewById(R.id.empty);
- empty.setVisibility(View.VISIBLE);
+ configureContentView(mIntents, initialIntents, rList, alwaysUseOption);
- mAdapterView = (AbsListView) findViewById(R.id.resolver_list);
- mAdapterView.setVisibility(View.GONE);
- }
// Prevent the Resolver window from becoming the top fullscreen window and thus from taking
// control of the system bars.
getWindow().clearFlags(FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR);
@@ -548,29 +496,6 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
}
}
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- if (mListView != null) {
- position -= mListView.getHeaderViewsCount();
- }
- if (position < 0) {
- // Header views don't count.
- return;
- }
- final int checkedPos = mAdapterView.getCheckedItemPosition();
- final boolean hasValidSelection = checkedPos != ListView.INVALID_POSITION;
- if (mAlwaysUseOption && (!hasValidSelection || mLastSelected != checkedPos)) {
- setAlwaysButtonEnabled(hasValidSelection, checkedPos, true);
- mOnceButton.setEnabled(hasValidSelection);
- if (hasValidSelection) {
- mAdapterView.smoothScrollToPosition(checkedPos);
- }
- mLastSelected = checkedPos;
- } else {
- startSelected(position, false, true);
- }
- }
-
private boolean hasManagedProfile() {
UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
if (userManager == null) {
@@ -831,14 +756,68 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
startActivity(in);
}
- ResolveListAdapter createAdapter(Context context, Intent[] initialIntents,
- List<ResolveInfo> rList, int launchedFromUid, boolean filterLastUsed) {
- return new ResolveListAdapter(context, initialIntents, rList, launchedFromUid,
- filterLastUsed);
+ ResolveListAdapter createAdapter(Context context, List<Intent> payloadIntents,
+ Intent[] initialIntents, List<ResolveInfo> rList, int launchedFromUid,
+ boolean filterLastUsed) {
+ return new ResolveListAdapter(context, payloadIntents, initialIntents, rList,
+ launchedFromUid, filterLastUsed);
}
- ResolveListAdapter getAdapter() {
- return mAdapter;
+ void configureContentView(List<Intent> payloadIntents, Intent[] initialIntents,
+ List<ResolveInfo> rList, boolean alwaysUseOption) {
+ mAdapter = createAdapter(this, payloadIntents, initialIntents, rList,
+ mLaunchedFromUid, alwaysUseOption);
+
+ final int layoutId;
+ if (mAdapter.hasFilteredItem()) {
+ layoutId = R.layout.resolver_list_with_default;
+ alwaysUseOption = false;
+ } else {
+ layoutId = getLayoutResource();
+ }
+ mAlwaysUseOption = alwaysUseOption;
+
+ int count = mAdapter.mDisplayList.size();
+ if (count > 1 || (count == 1 && mAdapter.getOtherProfile() != null)) {
+ setContentView(layoutId);
+ mAdapterView = (AbsListView) findViewById(R.id.resolver_list);
+ onPrepareAdapterView(mAdapterView, mAdapter, alwaysUseOption);
+ } else if (count == 1) {
+ safelyStartActivity(mAdapter.targetInfoForPosition(0, false));
+ mPackageMonitor.unregister();
+ mRegistered = false;
+ finish();
+ return;
+ } else {
+ setContentView(R.layout.resolver_list);
+
+ final TextView empty = (TextView) findViewById(R.id.empty);
+ empty.setVisibility(View.VISIBLE);
+
+ mAdapterView = (AbsListView) findViewById(R.id.resolver_list);
+ mAdapterView.setVisibility(View.GONE);
+ }
+ }
+
+ void onPrepareAdapterView(AbsListView adapterView, ResolveListAdapter adapter,
+ boolean alwaysUseOption) {
+ final boolean useHeader = adapter.hasFilteredItem();
+ final ListView listView = adapterView instanceof ListView ? (ListView) adapterView : null;
+
+ adapterView.setAdapter(mAdapter);
+
+ final ItemClickListener listener = new ItemClickListener();
+ adapterView.setOnItemClickListener(listener);
+ adapterView.setOnItemLongClickListener(listener);
+
+ if (alwaysUseOption) {
+ listView.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
+ }
+
+ if (useHeader && listView != null) {
+ listView.addHeaderView(LayoutInflater.from(this).inflate(
+ R.layout.resolver_different_item_header, listView, false));
+ }
}
final class DisplayResolveInfo implements TargetInfo {
@@ -888,6 +867,10 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
return mDisplayIcon;
}
+ public Drawable getBadgeIcon() {
+ return null;
+ }
+
@Override
public TargetInfo cloneFilledIn(Intent fillInIntent, int flags) {
return new DisplayResolveInfo(this, fillInIntent, flags);
@@ -1024,6 +1007,11 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
public Drawable getDisplayIcon();
/**
+ * @return The (small) icon to badge the target with
+ */
+ public Drawable getBadgeIcon();
+
+ /**
* Clone this target with the given fill-in information.
*/
public TargetInfo cloneFilledIn(Intent fillInIntent, int flags);
@@ -1035,6 +1023,7 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
}
class ResolveListAdapter extends BaseAdapter {
+ private final List<Intent> mIntents;
private final Intent[] mInitialIntents;
private final List<ResolveInfo> mBaseResolveList;
private ResolveInfo mLastChosen;
@@ -1050,8 +1039,10 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
private int mLastChosenPosition = -1;
private boolean mFilterLastUsed;
- public ResolveListAdapter(Context context, Intent[] initialIntents,
- List<ResolveInfo> rList, int launchedFromUid, boolean filterLastUsed) {
+ public ResolveListAdapter(Context context, List<Intent> payloadIntents,
+ Intent[] initialIntents, List<ResolveInfo> rList, int launchedFromUid,
+ boolean filterLastUsed) {
+ mIntents = payloadIntents;
mInitialIntents = initialIntents;
mBaseResolveList = rList;
mLaunchedFromUid = launchedFromUid;
@@ -1430,15 +1421,19 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
View view = convertView;
if (view == null) {
view = createView(parent);
-
- final ViewHolder holder = new ViewHolder(view);
- view.setTag(holder);
}
- bindView(view, getItem(position));
+ onBindView(view, getItem(position));
return view;
}
- public View createView(ViewGroup parent) {
+ public final View createView(ViewGroup parent) {
+ final View view = onCreateView(parent);
+ final ViewHolder holder = new ViewHolder(view);
+ view.setTag(holder);
+ return view;
+ }
+
+ public View onCreateView(ViewGroup parent) {
return mInflater.inflate(
com.android.internal.R.layout.resolve_list_item, parent, false);
}
@@ -1447,7 +1442,11 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
return !TextUtils.isEmpty(info.getExtendedInfo());
}
- private final void bindView(View view, TargetInfo info) {
+ public final void bindView(int position, View view) {
+ onBindView(view, getItem(position));
+ }
+
+ private void onBindView(View view, TargetInfo info) {
final ViewHolder holder = (ViewHolder) view.getTag();
holder.text.setText(info.getDisplayLabel());
if (showsExtendedInfo(info)) {
@@ -1461,6 +1460,15 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
new LoadAdapterIconTask((DisplayResolveInfo) info).execute();
}
holder.icon.setImageDrawable(info.getDisplayIcon());
+ if (holder.badge != null) {
+ final Drawable badge = info.getBadgeIcon();
+ if (badge != null) {
+ holder.badge.setImageDrawable(badge);
+ holder.badge.setVisibility(View.VISIBLE);
+ } else {
+ holder.badge.setVisibility(View.GONE);
+ }
+ }
}
}
@@ -1514,20 +1522,47 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic
public TextView text;
public TextView text2;
public ImageView icon;
+ public ImageView badge;
public ViewHolder(View view) {
text = (TextView) view.findViewById(com.android.internal.R.id.text1);
text2 = (TextView) view.findViewById(com.android.internal.R.id.text2);
icon = (ImageView) view.findViewById(R.id.icon);
+ badge = (ImageView) view.findViewById(R.id.target_badge);
}
}
- class ItemLongClickListener implements AdapterView.OnItemLongClickListener {
+ class ItemClickListener implements AdapterView.OnItemClickListener,
+ AdapterView.OnItemLongClickListener {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ final ListView listView = parent instanceof ListView ? (ListView) parent : null;
+ if (listView != null) {
+ position -= listView.getHeaderViewsCount();
+ }
+ if (position < 0) {
+ // Header views don't count.
+ return;
+ }
+ final int checkedPos = mAdapterView.getCheckedItemPosition();
+ final boolean hasValidSelection = checkedPos != ListView.INVALID_POSITION;
+ if (mAlwaysUseOption && (!hasValidSelection || mLastSelected != checkedPos)) {
+ setAlwaysButtonEnabled(hasValidSelection, checkedPos, true);
+ mOnceButton.setEnabled(hasValidSelection);
+ if (hasValidSelection) {
+ mAdapterView.smoothScrollToPosition(checkedPos);
+ }
+ mLastSelected = checkedPos;
+ } else {
+ startSelected(position, false, true);
+ }
+ }
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
- if (mListView != null) {
- position -= mListView.getHeaderViewsCount();
+ final ListView listView = parent instanceof ListView ? (ListView) parent : null;
+ if (listView != null) {
+ position -= listView.getHeaderViewsCount();
}
if (position < 0) {
// Header views don't count.
diff --git a/core/res/res/layout/chooser_grid.xml b/core/res/res/layout/chooser_grid.xml
index 0fa82ebcb9d6..dcdfb6c318d4 100644
--- a/core/res/res/layout/chooser_grid.xml
+++ b/core/res/res/layout/chooser_grid.xml
@@ -21,7 +21,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:maxWidth="@dimen/resolver_max_width"
- android:maxCollapsedHeight="256dp"
+ android:maxCollapsedHeight="288dp"
android:maxCollapsedHeightSmall="56dp"
android:id="@id/contentPanel">
@@ -30,24 +30,25 @@
android:layout_height="wrap_content"
android:layout_alwaysShow="true"
android:elevation="8dp"
- android:paddingStart="?attr/dialogPreferredPadding"
+ android:paddingStart="16dp"
android:background="@color/white" >
<ImageView android:id="@+id/title_icon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="start|center_vertical"
android:layout_marginEnd="16dp"
+ android:visibility="gone"
android:scaleType="fitCenter" />
<TextView android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:minHeight="56dp"
android:textAppearance="?attr/textAppearanceMedium"
+ android:textSize="14sp"
android:gravity="start|center_vertical"
android:paddingEnd="?attr/dialogPreferredPadding"
- android:paddingTop="8dp"
- android:paddingBottom="8dp" />
+ android:paddingTop="12dp"
+ android:paddingBottom="12dp" />
<LinearLayout android:id="@+id/profile_button"
android:layout_width="wrap_content"
android:layout_height="48dp"
@@ -82,23 +83,24 @@
</LinearLayout>
</LinearLayout>
- <GridView
+ <ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/resolver_list"
android:clipToPadding="false"
- android:paddingStart="@dimen/chooser_grid_padding"
- android:paddingEnd="@dimen/chooser_grid_padding"
android:scrollbarStyle="outsideOverlay"
android:background="@color/white"
android:elevation="8dp"
- android:numColumns="4"
+ android:listSelector="@color/transparent"
+ android:divider="@null"
+ android:scrollIndicators="top"
android:nestedScrollingEnabled="true" />
<TextView android:id="@+id/empty"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alwaysShow="true"
+ android:background="@color/white"
android:text="@string/noApplications"
android:padding="32dp"
android:gravity="center"
diff --git a/core/res/res/layout/chooser_row.xml b/core/res/res/layout/chooser_row.xml
new file mode 100644
index 000000000000..9baa32c67f3f
--- /dev/null
+++ b/core/res/res/layout/chooser_row.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2015, 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.
+*/
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="match_parent" android:layout_height="wrap_content"
+ android:minHeight="80dp"
+ android:gravity="start|top"
+ android:paddingTop="8dp"
+ android:paddingBottom="8dp"
+ android:paddingStart="@dimen/chooser_grid_padding"
+ android:paddingEnd="@dimen/chooser_grid_padding"
+ android:weightSum="4">
+
+</LinearLayout>
+
diff --git a/core/res/res/layout/resolve_grid_item.xml b/core/res/res/layout/resolve_grid_item.xml
index 664b02fdbb60..1c496f6435d6 100644
--- a/core/res/res/layout/resolve_grid_item.xml
+++ b/core/res/res/layout/resolve_grid_item.xml
@@ -18,18 +18,31 @@
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
- android:layout_width="match_parent" android:layout_height="wrap_content"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
android:minWidth="80dp"
android:gravity="center"
android:paddingTop="8dp"
android:paddingBottom="8dp"
- android:background="?attr/activatedBackgroundIndicator">
+ android:background="?attr/selectableItemBackgroundBorderless">
- <!-- Activity icon when presenting dialog -->
- <ImageView android:id="@+id/icon"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:scaleType="fitCenter" />
+ <FrameLayout android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <ImageView android:id="@+id/icon"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:layout_marginLeft="3dp"
+ android:layout_marginRight="3dp"
+ android:layout_marginBottom="3dp"
+ android:scaleType="fitCenter" />
+ <ImageView android:id="@+id/target_badge"
+ android:layout_width="16dp"
+ android:layout_height="16dp"
+ android:layout_gravity="end|bottom"
+ android:visibility="gone"
+ android:scaleType="fitCenter" />
+ </FrameLayout>
<!-- Activity name -->
<TextView android:id="@android:id/text1"
@@ -40,21 +53,23 @@
android:layout_marginRight="4dp"
android:textAppearance="?attr/textAppearanceSmall"
android:textColor="?attr/textColorPrimary"
+ android:textSize="12sp"
android:fontFamily="sans-serif-condensed"
- android:gravity="center"
+ android:gravity="top|center_horizontal"
android:minLines="2"
android:maxLines="2"
android:ellipsize="marquee" />
<!-- Extended activity info to distinguish between duplicate activity names -->
<TextView android:id="@android:id/text2"
android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textSize="12sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:minLines="2"
android:maxLines="2"
- android:gravity="center"
+ android:gravity="top|center_horizontal"
android:ellipsize="marquee" />
</LinearLayout>
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index b9825c534705..7f8c460bda4c 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -174,4 +174,6 @@
<color name="Pink_800">#ffad1457</color>
<color name="Red_700">#ffc53929</color>
<color name="Red_800">#ffb93221</color>
+
+ <color name="chooser_service_row_background_color">#fff5f5f5</color>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 801a98a679d0..4e6c057680ed 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2257,4 +2257,8 @@
<java-symbol type="id" name="day_picker_view_pager" />
<java-symbol type="layout" name="day_picker_content_material" />
<java-symbol type="drawable" name="scroll_indicator_material" />
+
+ <java-symbol type="layout" name="chooser_row" />
+ <java-symbol type="color" name="chooser_service_row_background_color" />
+ <java-symbol type="id" name="target_badge" />
</resources>