diff options
| -rw-r--r-- | core/java/com/android/internal/app/IntentForwarderActivity.java | 2 | ||||
| -rw-r--r-- | core/java/com/android/internal/app/ResolverActivity.java | 103 | ||||
| -rw-r--r-- | core/java/com/android/internal/app/ResolverComparator.java | 30 | ||||
| -rw-r--r-- | core/res/AndroidManifest.xml | 13 | ||||
| -rw-r--r-- | packages/SystemUI/AndroidManifest.xml | 19 | ||||
| -rw-r--r-- | packages/SystemUI/res/values/arrays.xml | 12 | ||||
| -rw-r--r-- | packages/SystemUI/res/values/strings.xml | 5 | ||||
| -rw-r--r-- | packages/SystemUI/src/com/android/systemui/chooser/ChooserActivity.java (renamed from core/java/com/android/internal/app/ChooserActivity.java) | 65 | ||||
| -rw-r--r-- | packages/SystemUI/src/com/android/systemui/chooser/ResolverTargetActionsDialogFragment.java | 98 |
9 files changed, 280 insertions, 67 deletions
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java index dbec7405fe49..12449871bad9 100644 --- a/core/java/com/android/internal/app/IntentForwarderActivity.java +++ b/core/java/com/android/internal/app/IntentForwarderActivity.java @@ -100,7 +100,7 @@ public class IntentForwarderActivity extends Activity { final boolean shouldShowDisclosure = ri == null || ri.activityInfo == null || !"android".equals(ri.activityInfo.packageName) || !(ResolverActivity.class.getName().equals(ri.activityInfo.name) - || ChooserActivity.class.getName().equals(ri.activityInfo.name)); + || "com.android.systemui.chooser.ChooserActivity".equals(ri.activityInfo.name)); try { startActivityAsCaller(newIntent, null, false, targetUserId); diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index aa38de737484..4e48c1b4c166 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -22,6 +22,7 @@ import android.app.ActivityThread; import android.app.VoiceInteractor.PickOptionRequest; import android.app.VoiceInteractor.PickOptionRequest.Option; import android.app.VoiceInteractor.Prompt; +import android.content.pm.ComponentInfo; import android.os.AsyncTask; import android.provider.Settings; import android.text.TextUtils; @@ -336,12 +337,12 @@ public class ResolverActivity extends Activity { /** * Perform any initialization needed for voice interaction. */ - void onSetupVoiceInteraction() { + public void onSetupVoiceInteraction() { // Do it right now. Subclasses may delay this and send it later. sendVoiceChoicesIfNeeded(); } - void sendVoiceChoicesIfNeeded() { + public void sendVoiceChoicesIfNeeded() { if (!isVoiceInteraction()) { // Clearly not needed. return; @@ -382,7 +383,7 @@ public class ResolverActivity extends Activity { return null; } - int getLayoutResource() { + public int getLayoutResource() { return R.layout.resolver_list; } @@ -591,7 +592,7 @@ public class ResolverActivity extends Activity { mAlwaysUseOption); } - void startSelected(int which, boolean always, boolean filtered) { + public void startSelected(int which, boolean always, boolean filtered) { if (isFinishing()) { return; } @@ -761,7 +762,7 @@ public class ResolverActivity extends Activity { return true; } - void safelyStartActivity(TargetInfo cti) { + public void safelyStartActivity(TargetInfo cti) { // If needed, show that intent is forwarded // from managed profile to owner or other way around. if (mProfileSwitchMessageId != -1) { @@ -791,26 +792,26 @@ public class ResolverActivity extends Activity { } } - void onActivityStarted(TargetInfo cti) { + public void onActivityStarted(TargetInfo cti) { // Do nothing } - boolean shouldGetActivityMetadata() { + public boolean shouldGetActivityMetadata() { return false; } - boolean shouldAutoLaunchSingleChoice(TargetInfo target) { + public boolean shouldAutoLaunchSingleChoice(TargetInfo target) { return true; } - void showAppDetails(ResolveInfo ri) { + public void showTargetDetails(ResolveInfo ri) { Intent in = new Intent().setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) .setData(Uri.fromParts("package", ri.activityInfo.packageName, null)) .addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT); startActivity(in); } - ResolveListAdapter createAdapter(Context context, List<Intent> payloadIntents, + public ResolveListAdapter createAdapter(Context context, List<Intent> payloadIntents, Intent[] initialIntents, List<ResolveInfo> rList, int launchedFromUid, boolean filterLastUsed) { return new ResolveListAdapter(context, payloadIntents, initialIntents, rList, @@ -820,7 +821,7 @@ public class ResolverActivity extends Activity { /** * Returns true if the activity is finishing and creation should halt */ - boolean configureContentView(List<Intent> payloadIntents, Intent[] initialIntents, + public boolean configureContentView(List<Intent> payloadIntents, Intent[] initialIntents, List<ResolveInfo> rList, boolean alwaysUseOption) { // The last argument of createAdapter is whether to do special handling // of the last used choice to highlight it in the list. We need to always @@ -867,7 +868,7 @@ public class ResolverActivity extends Activity { return false; } - void onPrepareAdapterView(AbsListView adapterView, ResolveListAdapter adapter, + public void onPrepareAdapterView(AbsListView adapterView, ResolveListAdapter adapter, boolean alwaysUseOption) { final boolean useHeader = adapter.hasFilteredItem(); final ListView listView = adapterView instanceof ListView ? (ListView) adapterView : null; @@ -898,7 +899,7 @@ public class ResolverActivity extends Activity { && Objects.equals(lhs.activityInfo.packageName, rhs.activityInfo.packageName); } - final class DisplayResolveInfo implements TargetInfo { + public final class DisplayResolveInfo implements TargetInfo { private final ResolveInfo mResolveInfo; private final CharSequence mDisplayLabel; private Drawable mDisplayIcon; @@ -906,8 +907,9 @@ public class ResolverActivity extends Activity { private final CharSequence mExtendedInfo; private final Intent mResolvedIntent; private final List<Intent> mSourceIntents = new ArrayList<>(); + private boolean mPinned; - DisplayResolveInfo(Intent originalIntent, ResolveInfo pri, CharSequence pLabel, + public DisplayResolveInfo(Intent originalIntent, ResolveInfo pri, CharSequence pLabel, CharSequence pInfo, Intent pOrigIntent) { mSourceIntents.add(originalIntent); mResolveInfo = pri; @@ -932,6 +934,7 @@ public class ResolverActivity extends Activity { mExtendedInfo = other.mExtendedInfo; mResolvedIntent = new Intent(other.mResolvedIntent); mResolvedIntent.fillIn(fillInIntent, flags); + mPinned = other.mPinned; } public ResolveInfo getResolveInfo() { @@ -1026,6 +1029,15 @@ public class ResolverActivity extends Activity { activity.startActivityAsUser(mResolvedIntent, options, user); return false; } + + @Override + public boolean isPinned() { + return mPinned; + } + + public void setPinned(boolean pinned) { + mPinned = pinned; + } } /** @@ -1039,7 +1051,7 @@ public class ResolverActivity extends Activity { * * @return the resolved intent for this target */ - public Intent getResolvedIntent(); + Intent getResolvedIntent(); /** * Get the resolved component name that represents this target. Note that this may not @@ -1048,7 +1060,7 @@ public class ResolverActivity extends Activity { * * @return the resolved ComponentName for this target */ - public ComponentName getResolvedComponentName(); + ComponentName getResolvedComponentName(); /** * Start the activity referenced by this target. @@ -1057,7 +1069,7 @@ public class ResolverActivity extends Activity { * @param options ActivityOptions bundle * @return true if the start completed successfully */ - public boolean start(Activity activity, Bundle options); + boolean start(Activity activity, Bundle options); /** * Start the activity referenced by this target as if the ResolverActivity's caller @@ -1068,7 +1080,7 @@ public class ResolverActivity extends Activity { * @param userId userId to start as or {@link UserHandle#USER_NULL} for activity's caller * @return true if the start completed successfully */ - public boolean startAsCaller(Activity activity, Bundle options, int userId); + boolean startAsCaller(Activity activity, Bundle options, int userId); /** * Start the activity referenced by this target as a given user. @@ -1078,7 +1090,7 @@ public class ResolverActivity extends Activity { * @param user handle for the user to start the activity as * @return true if the start completed successfully */ - public boolean startAsUser(Activity activity, Bundle options, UserHandle user); + boolean startAsUser(Activity activity, Bundle options, UserHandle user); /** * Return the ResolveInfo about how and why this target matched the original query @@ -1086,14 +1098,14 @@ public class ResolverActivity extends Activity { * * @return ResolveInfo representing this target's match */ - public ResolveInfo getResolveInfo(); + ResolveInfo getResolveInfo(); /** * Return the human-readable text label for this target. * * @return user-visible target label */ - public CharSequence getDisplayLabel(); + CharSequence getDisplayLabel(); /** * Return any extended info for this target. This may be used to disambiguate @@ -1101,35 +1113,40 @@ public class ResolverActivity extends Activity { * * @return human-readable disambig string or null if none present */ - public CharSequence getExtendedInfo(); + CharSequence getExtendedInfo(); /** * @return The drawable that should be used to represent this target */ - public Drawable getDisplayIcon(); + Drawable getDisplayIcon(); /** * @return The (small) icon to badge the target with */ - public Drawable getBadgeIcon(); + Drawable getBadgeIcon(); /** * @return The content description for the badge icon */ - public CharSequence getBadgeContentDescription(); + CharSequence getBadgeContentDescription(); /** * Clone this target with the given fill-in information. */ - public TargetInfo cloneFilledIn(Intent fillInIntent, int flags); + TargetInfo cloneFilledIn(Intent fillInIntent, int flags); /** * @return the list of supported source intents deduped against this single target */ - public List<Intent> getAllSourceIntents(); + List<Intent> getAllSourceIntents(); + + /** + * @return true if this target should be pinned to the front by the request of the user + */ + boolean isPinned(); } - class ResolveListAdapter extends BaseAdapter { + public class ResolveListAdapter extends BaseAdapter { private final List<Intent> mIntents; private final Intent[] mInitialIntents; private final List<ResolveInfo> mBaseResolveList; @@ -1372,9 +1389,12 @@ public class ResolverActivity extends Activity { } } if (!found) { - into.add(new ResolvedComponentInfo(new ComponentName( - newInfo.activityInfo.packageName, newInfo.activityInfo.name), - intent, newInfo)); + final ComponentName name = new ComponentName( + newInfo.activityInfo.packageName, newInfo.activityInfo.name); + final ResolvedComponentInfo rci = new ResolvedComponentInfo(name, + intent, newInfo); + rci.setPinned(isComponentPinned(name)); + into.add(rci); } } } @@ -1450,6 +1470,8 @@ public class ResolverActivity extends Activity { final Intent replaceIntent = getReplacementIntent(add.activityInfo, intent); final DisplayResolveInfo dri = new DisplayResolveInfo(intent, add, roLabel, extraInfo, replaceIntent); + final ComponentInfo ci = add.getComponentInfo(); + dri.setPinned(rci.isPinned()); addResolveInfo(dri); if (replaceIntent == intent) { // Only add alternates if we didn't get a specific replacement from @@ -1533,11 +1555,11 @@ public class ResolverActivity extends Activity { return false; } - protected int getDisplayResolveInfoCount() { + public int getDisplayResolveInfoCount() { return mDisplayList.size(); } - protected DisplayResolveInfo getDisplayResolveInfo(int index) { + public DisplayResolveInfo getDisplayResolveInfo(int index) { // Used to query services. We only query services for primary targets, not alternates. return mDisplayList.get(index); } @@ -1567,6 +1589,10 @@ public class ResolverActivity extends Activity { return !TextUtils.isEmpty(info.getExtendedInfo()); } + public boolean isComponentPinned(ComponentName name) { + return false; + } + public final void bindView(int position, View view) { onBindView(view, getItem(position)); } @@ -1603,6 +1629,7 @@ public class ResolverActivity extends Activity { static final class ResolvedComponentInfo { public final ComponentName name; + private boolean mPinned; private final List<Intent> mIntents = new ArrayList<>(); private final List<ResolveInfo> mResolveInfos = new ArrayList<>(); @@ -1645,6 +1672,14 @@ public class ResolverActivity extends Activity { } return -1; } + + public boolean isPinned() { + return mPinned; + } + + public void setPinned(boolean pinned) { + mPinned = pinned; + } } static class ViewHolder { @@ -1698,7 +1733,7 @@ public class ResolverActivity extends Activity { return false; } ResolveInfo ri = mAdapter.resolveInfoForPosition(position, true); - showAppDetails(ri); + showTargetDetails(ri); return true; } diff --git a/core/java/com/android/internal/app/ResolverComparator.java b/core/java/com/android/internal/app/ResolverComparator.java index 31556e29bc32..964a7f53e357 100644 --- a/core/java/com/android/internal/app/ResolverComparator.java +++ b/core/java/com/android/internal/app/ResolverComparator.java @@ -48,7 +48,7 @@ class ResolverComparator implements Comparator<ResolvedComponentInfo> { private static final boolean DEBUG = false; // Two weeks - private static final long USAGE_STATS_PERIOD = 1000 * 60 * 60 * 24 * 14; + private static final long USAGE_STATS_PERIOD = 1000 * 60 * 60 * 24 * 7; private static final long RECENCY_TIME_PERIOD = 1000 * 60 * 60 * 12; @@ -171,15 +171,27 @@ class ResolverComparator implements Comparator<ResolvedComponentInfo> { } } - if (mStats != null) { - final ScoredTarget lhsTarget = mScoredTargets.get(new ComponentName( - lhs.activityInfo.packageName, lhs.activityInfo.name)); - final ScoredTarget rhsTarget = mScoredTargets.get(new ComponentName( - rhs.activityInfo.packageName, rhs.activityInfo.name)); - final float diff = rhsTarget.score - lhsTarget.score; + final boolean lPinned = lhsp.isPinned(); + final boolean rPinned = rhsp.isPinned(); - if (diff != 0) { - return diff > 0 ? 1 : -1; + if (lPinned && !rPinned) { + return -1; + } else if (!lPinned && rPinned) { + return 1; + } + + // Pinned items stay stable within a normal lexical sort and ignore scoring. + if (!lPinned && !rPinned) { + if (mStats != null) { + final ScoredTarget lhsTarget = mScoredTargets.get(new ComponentName( + lhs.activityInfo.packageName, lhs.activityInfo.name)); + final ScoredTarget rhsTarget = mScoredTargets.get(new ComponentName( + rhs.activityInfo.packageName, rhs.activityInfo.name)); + final float diff = rhsTarget.score - lhsTarget.score; + + if (diff != 0) { + return diff > 0 ? 1 : -1; + } } } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 1c3db104dc3c..4ab81e990513 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2887,19 +2887,6 @@ android:theme="@style/Theme.Material.DayNight.DarkActionBar" android:forceDeviceEncrypted="true" android:encryptionAware="true"> - <activity android:name="com.android.internal.app.ChooserActivity" - android:theme="@style/Theme.DeviceDefault.Resolver" - android:finishOnCloseSystemDialogs="true" - android:excludeFromRecents="true" - android:documentLaunchMode="never" - android:relinquishTaskIdentity="true" - android:process=":ui"> - <intent-filter> - <action android:name="android.intent.action.CHOOSER" /> - <category android:name="android.intent.category.DEFAULT" /> - <category android:name="android.intent.category.VOICE" /> - </intent-filter> - </activity> <activity android:name="com.android.internal.app.IntentForwarderActivity" android:finishOnCloseSystemDialogs="true" android:theme="@style/Theme.NoDisplay" diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 21abb901cb9a..52b7b7dfc128 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -155,6 +155,10 @@ <!-- TV picture-in-picture --> <uses-permission android:name="android.permission.RECEIVE_MEDIA_RESOURCE_USAGE" /> + <!-- ChooserActivity --> + <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" /> + <uses-permission android:name="android.permission.BIND_CHOOSER_TARGET_SERVICE" /> + <application android:name=".SystemUIApplication" android:persistent="true" @@ -438,5 +442,20 @@ <action android:name="com.android.systemui.action.CLEAR_TUNER" /> </intent-filter> </receiver> + + <activity android:name=".chooser.ChooserActivity" + android:theme="@*android:style/Theme.DeviceDefault.Resolver" + android:finishOnCloseSystemDialogs="true" + android:excludeFromRecents="true" + android:documentLaunchMode="never" + android:relinquishTaskIdentity="true" + android:process=":chooser"> + <intent-filter> + <action android:name="android.intent.action.CHOOSER" /> + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.VOICE" /> + </intent-filter> + </activity> + </application> </manifest> diff --git a/packages/SystemUI/res/values/arrays.xml b/packages/SystemUI/res/values/arrays.xml index bf0cba22ab0c..32025e06e5b9 100644 --- a/packages/SystemUI/res/values/arrays.xml +++ b/packages/SystemUI/res/values/arrays.xml @@ -51,4 +51,16 @@ <item>0</item><item>3</item> <item>3</item><item>3</item> </array> + + <!-- Used in ResolverTargetActionsDialogFragment --> + <string-array name="resolver_target_actions_pin"> + <item>@string/pin_target</item> + <item>@string/app_info</item> + </string-array> + + <string-array name="resolver_target_actions_unpin"> + <item>@string/unpin_target</item> + <item>@string/app_info</item> + </string-array> + </resources> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index b09693444bdf..707225c6b7ea 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -1338,4 +1338,9 @@ <!-- Accessibility description for data saver being off [CHAR LIMIT=NONE] --> <string name="accessibility_data_saver_off">Data Saver is off</string> + <!-- Resolver target actions strings --> + <string name="pin_target">Pin</string> + <string name="unpin_target">Unpin</string> + <string name="app_info">App info</string> + </resources> diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/packages/SystemUI/src/com/android/systemui/chooser/ChooserActivity.java index 27333915b2b6..a8bc36e58e19 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/packages/SystemUI/src/com/android/systemui/chooser/ChooserActivity.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.internal.app; +package com.android.systemui.chooser; import android.animation.ObjectAnimator; import android.annotation.NonNull; @@ -25,6 +25,7 @@ import android.content.Intent; import android.content.IntentSender; import android.content.IntentSender.SendIntentException; import android.content.ServiceConnection; +import android.content.SharedPreferences; import android.content.pm.ActivityInfo; import android.content.pm.LabeledIntent; import android.content.pm.PackageManager; @@ -35,6 +36,7 @@ import android.graphics.Color; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; import android.os.Bundle; +import android.os.Environment; import android.os.Handler; import android.os.IBinder; import android.os.Message; @@ -65,9 +67,12 @@ import android.widget.AbsListView; import android.widget.BaseAdapter; import android.widget.ListView; import com.android.internal.R; +import com.android.internal.app.IntentForwarderActivity; +import com.android.internal.app.ResolverActivity; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto.MetricsEvent; +import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -91,6 +96,11 @@ public class ChooserActivity extends ResolverActivity { private ChooserListAdapter mChooserListAdapter; private ChooserRowAdapter mChooserRowAdapter; + private SharedPreferences mPinnedSharedPrefs; + private static final float PINNED_TARGET_SCORE_BOOST = 1000.f; + private static final String PINNED_SHARED_PREFS_NAME = "chooser_pin_settings"; + private static final String TARGET_DETAILS_FRAGMENT_TAG = "targetDetailsFragment"; + private final List<ChooserTargetServiceConnection> mServiceConnections = new ArrayList<>(); private static final int CHOOSER_TARGET_SERVICE_RESULT = 1; @@ -207,12 +217,18 @@ public class ChooserActivity extends ResolverActivity { mRefinementIntentSender = intent.getParcelableExtra( Intent.EXTRA_CHOOSER_REFINEMENT_INTENT_SENDER); setSafeForwardingMode(true); + + mPinnedSharedPrefs = getPinnedSharedPrefs(this); super.onCreate(savedInstanceState, target, title, defaultTitleRes, initialIntents, null, false); MetricsLogger.action(this, MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN); } + static SharedPreferences getPinnedSharedPrefs(Context context) { + return context.getSharedPreferences(PINNED_SHARED_PREFS_NAME, MODE_PRIVATE); + } + @Override protected void onDestroy() { super.onDestroy(); @@ -243,7 +259,7 @@ public class ChooserActivity extends ResolverActivity { } @Override - void onActivityStarted(TargetInfo cti) { + public void onActivityStarted(TargetInfo cti) { if (mChosenComponentSender != null) { final ComponentName target = cti.getResolvedComponentName(); if (target != null) { @@ -259,7 +275,7 @@ public class ChooserActivity extends ResolverActivity { } @Override - void onPrepareAdapterView(AbsListView adapterView, ResolveListAdapter adapter, + public void onPrepareAdapterView(AbsListView adapterView, ResolveListAdapter adapter, boolean alwaysUseOption) { final ListView listView = adapterView instanceof ListView ? (ListView) adapterView : null; mChooserListAdapter = (ChooserListAdapter) adapter; @@ -272,17 +288,17 @@ public class ChooserActivity extends ResolverActivity { } @Override - int getLayoutResource() { + public int getLayoutResource() { return R.layout.chooser_grid; } @Override - boolean shouldGetActivityMetadata() { + public boolean shouldGetActivityMetadata() { return true; } @Override - boolean shouldAutoLaunchSingleChoice(TargetInfo target) { + public boolean shouldAutoLaunchSingleChoice(TargetInfo target) { final Intent intent = target.getResolvedIntent(); final ResolveInfo resolve = target.getResolveInfo(); @@ -299,6 +315,16 @@ public class ChooserActivity extends ResolverActivity { return false; } + @Override + public void showTargetDetails(ResolveInfo ri) { + ComponentName name = ri.activityInfo.getComponentName(); + boolean pinned = mPinnedSharedPrefs.getBoolean(name.flattenToString(), false); + ResolverTargetActionsDialogFragment f = + new ResolverTargetActionsDialogFragment(ri.loadLabel(getPackageManager()), + name, pinned); + f.show(getFragmentManager(), TARGET_DETAILS_FRAGMENT_TAG); + } + private void modifyTargetIntent(Intent in) { final String action = in.getAction(); if (Intent.ACTION_SEND.equals(action) || @@ -340,7 +366,7 @@ public class ChooserActivity extends ResolverActivity { } @Override - void startSelected(int which, boolean always, boolean filtered) { + public void startSelected(int which, boolean always, boolean filtered) { super.startSelected(which, always, filtered); if (mChooserListAdapter != null) { @@ -471,7 +497,7 @@ public class ChooserActivity extends ResolverActivity { mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT); } - void onSetupVoiceInteraction() { + public void onSetupVoiceInteraction() { // Do nothing. We'll send the voice stuff ourselves. } @@ -543,7 +569,7 @@ public class ChooserActivity extends ResolverActivity { } @Override - ResolveListAdapter createAdapter(Context context, List<Intent> payloadIntents, + public ResolveListAdapter createAdapter(Context context, List<Intent> payloadIntents, Intent[] initialIntents, List<ResolveInfo> rList, int launchedFromUid, boolean filterLastUsed) { final ChooserListAdapter adapter = new ChooserListAdapter(context, payloadIntents, @@ -711,6 +737,11 @@ public class ChooserActivity extends ResolverActivity { } return results; } + + @Override + public boolean isPinned() { + return mSourceInfo != null ? mSourceInfo.isPinned() : false; + } } public class ChooserListAdapter extends ResolveListAdapter { @@ -777,6 +808,20 @@ public class ChooserActivity extends ResolverActivity { } @Override + public boolean isComponentPinned(ComponentName name) { + return mPinnedSharedPrefs.getBoolean(name.flattenToString(), false); + } + + @Override + public float getScore(DisplayResolveInfo target) { + float score = super.getScore(target); + if (target.isPinned()) { + score += PINNED_TARGET_SCORE_BOOST; + } + return score; + } + + @Override public View onCreateView(ViewGroup parent) { return mInflater.inflate( com.android.internal.R.layout.resolve_grid_item, parent, false); @@ -1121,7 +1166,7 @@ public class ChooserActivity extends ResolverActivity { v.setOnLongClickListener(new OnLongClickListener() { @Override public boolean onLongClick(View v) { - showAppDetails( + showTargetDetails( mChooserListAdapter.resolveInfoForPosition( holder.itemIndices[column], true)); return true; diff --git a/packages/SystemUI/src/com/android/systemui/chooser/ResolverTargetActionsDialogFragment.java b/packages/SystemUI/src/com/android/systemui/chooser/ResolverTargetActionsDialogFragment.java new file mode 100644 index 000000000000..839aa4556450 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/chooser/ResolverTargetActionsDialogFragment.java @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2016 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. + */ + + +package com.android.systemui.chooser; + +import android.app.AlertDialog.Builder; +import android.app.Dialog; +import android.app.DialogFragment; +import android.content.ComponentName; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.SharedPreferences; +import android.net.Uri; +import android.os.Bundle; +import android.provider.Settings; + +import com.android.systemui.R; + +/** + * Shows a dialog with actions to take on a chooser target + */ +public class ResolverTargetActionsDialogFragment extends DialogFragment + implements DialogInterface.OnClickListener { + private static final String NAME_KEY = "componentName"; + private static final String PINNED_KEY = "pinned"; + private static final String TITLE_KEY = "title"; + + // Sync with R.array.resolver_target_actions_* resources + private static final int TOGGLE_PIN_INDEX = 0; + private static final int APP_INFO_INDEX = 1; + + public ResolverTargetActionsDialogFragment() { + } + + public ResolverTargetActionsDialogFragment(CharSequence title, ComponentName name, + boolean pinned) { + Bundle args = new Bundle(); + args.putCharSequence(TITLE_KEY, title); + args.putParcelable(NAME_KEY, name); + args.putBoolean(PINNED_KEY, pinned); + setArguments(args); + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final Bundle args = getArguments(); + final int itemRes = args.getBoolean(PINNED_KEY, false) + ? R.array.resolver_target_actions_unpin + : R.array.resolver_target_actions_pin; + return new Builder(getContext()) + .setCancelable(true) + .setItems(itemRes, this) + .setTitle(args.getCharSequence(TITLE_KEY)) + .create(); + } + + @Override + public void onClick(DialogInterface dialog, int which) { + final Bundle args = getArguments(); + ComponentName name = args.getParcelable(NAME_KEY); + switch (which) { + case TOGGLE_PIN_INDEX: + SharedPreferences sp = ChooserActivity.getPinnedSharedPrefs(getContext()); + final String key = name.flattenToString(); + boolean currentVal = sp.getBoolean(name.flattenToString(), false); + if (currentVal) { + sp.edit().remove(key).apply(); + } else { + sp.edit().putBoolean(key, true).apply(); + } + + // Force the chooser to requery and resort things + getActivity().recreate(); + break; + case APP_INFO_INDEX: + Intent in = new Intent().setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) + .setData(Uri.fromParts("package", name.getPackageName(), null)) + .addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT); + startActivity(in); + break; + } + dismiss(); + } +} |