Merge "Make direct share work with the work profile tab."
This commit is contained in:
committed by
Android (Google) Code Review
commit
f82fd3dc81
@@ -156,14 +156,32 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter {
|
||||
@VisibleForTesting
|
||||
public abstract Object getAdapterForIndex(int pageIndex);
|
||||
|
||||
/**
|
||||
* Returns the {@link ResolverListAdapter} instance of the profile that represents
|
||||
* <code>userHandle</code>. If there is no such adapter for the specified
|
||||
* <code>userHandle</code>, returns {@code null}.
|
||||
* <p>For example, if there is a work profile on the device with user id 10, calling this method
|
||||
* with <code>UserHandle.of(10)</code> returns the work profile {@link ResolverListAdapter}.
|
||||
*/
|
||||
@Nullable
|
||||
abstract ResolverListAdapter getListAdapterForUserHandle(UserHandle userHandle);
|
||||
|
||||
/**
|
||||
* Returns the {@link ResolverListAdapter} instance of the profile that is currently visible
|
||||
* to the user.
|
||||
* <p>For example, if the user is viewing the work tab in the share sheet, this method returns
|
||||
* the work profile {@link ResolverListAdapter}.
|
||||
* @see #getInactiveListAdapter()
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public abstract ResolverListAdapter getActiveListAdapter();
|
||||
|
||||
/**
|
||||
* If this is a device with a work profile, returns the {@link ResolverListAdapter} instance
|
||||
* of the profile that is not the active one. Otherwise returns {@code null}. For example,
|
||||
* if the share sheet is launched in the work profile, this method returns the personal
|
||||
* profile {@link ResolverListAdapter}.
|
||||
* of the profile that is <b><i>not</i></b> currently visible to the user. Otherwise returns
|
||||
* {@code null}.
|
||||
* <p>For example, if the user is viewing the work tab in the share sheet, this method returns
|
||||
* the personal profile {@link ResolverListAdapter}.
|
||||
* @see #getActiveListAdapter()
|
||||
*/
|
||||
@VisibleForTesting
|
||||
|
||||
@@ -72,7 +72,6 @@ import android.os.IBinder;
|
||||
import android.os.Message;
|
||||
import android.os.Parcelable;
|
||||
import android.os.PatternMatcher;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ResultReceiver;
|
||||
import android.os.UserHandle;
|
||||
@@ -90,6 +89,7 @@ import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.HashedStringCache;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.util.Size;
|
||||
import android.util.Slog;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -150,6 +150,8 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
ChooserListAdapter.ChooserListCommunicator,
|
||||
SelectableTargetInfoCommunicator {
|
||||
private static final String TAG = "ChooserActivity";
|
||||
private AppPredictor mPersonalAppPredictor;
|
||||
private AppPredictor mWorkAppPredictor;
|
||||
|
||||
@UnsupportedAppUsage
|
||||
public ChooserActivity() {
|
||||
@@ -164,7 +166,7 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
|
||||
private static final String PREF_NUM_SHEET_EXPANSIONS = "pref_num_sheet_expansions";
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
private static final boolean DEBUG = true;
|
||||
|
||||
private static final boolean USE_PREDICTION_MANAGER_FOR_SHARE_ACTIVITIES = true;
|
||||
// TODO(b/123088566) Share these in a better way.
|
||||
@@ -177,9 +179,8 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
public static final int LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS = 250;
|
||||
|
||||
private boolean mIsAppPredictorComponentAvailable;
|
||||
private AppPredictor mAppPredictor;
|
||||
private AppPredictor.Callback mAppPredictorCallback;
|
||||
private Map<ChooserTarget, AppTarget> mDirectShareAppTargetCache;
|
||||
private Map<ChooserTarget, ShortcutInfo> mDirectShareShortcutInfoCache;
|
||||
|
||||
public static final int TARGET_TYPE_DEFAULT = 0;
|
||||
public static final int TARGET_TYPE_CHOOSER_TARGET = 1;
|
||||
@@ -239,7 +240,7 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
private static final int MAX_RANKED_TARGETS = 4;
|
||||
|
||||
private final List<ChooserTargetServiceConnection> mServiceConnections = new ArrayList<>();
|
||||
private final Set<ComponentName> mServicesRequested = new HashSet<>();
|
||||
private final Set<Pair<ComponentName, UserHandle>> mServicesRequested = new HashSet<>();
|
||||
|
||||
private static final int MAX_LOG_RANK_POSITION = 12;
|
||||
|
||||
@@ -422,6 +423,7 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
WATCHDOG_TIMEOUT_MIN_MILLIS);
|
||||
sendEmptyMessageDelayed(CHOOSER_TARGET_SERVICE_WATCHDOG_MAX_TIMEOUT,
|
||||
WATCHDOG_TIMEOUT_MAX_MILLIS);
|
||||
|
||||
}
|
||||
|
||||
private void maybeStopServiceRequestTimer() {
|
||||
@@ -454,10 +456,14 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
break;
|
||||
}
|
||||
if (sri.resultTargets != null) {
|
||||
// TODO(arangelov): Instead of using getCurrentListAdapter(), pass the
|
||||
// profileId as part of the message.
|
||||
mChooserMultiProfilePagerAdapter.getActiveListAdapter().addServiceResults(
|
||||
sri.originalTarget, sri.resultTargets, TARGET_TYPE_CHOOSER_TARGET);
|
||||
ChooserListAdapter adapterForUserHandle =
|
||||
mChooserMultiProfilePagerAdapter.getListAdapterForUserHandle(
|
||||
sri.userHandle);
|
||||
if (adapterForUserHandle != null) {
|
||||
adapterForUserHandle.addServiceResults(sri.originalTarget,
|
||||
sri.resultTargets, TARGET_TYPE_CHOOSER_TARGET,
|
||||
/* directShareShortcutInfoCache */ null);
|
||||
}
|
||||
}
|
||||
unbindService(sri.connection);
|
||||
sri.connection.destroy();
|
||||
@@ -480,15 +486,23 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
Log.d(TAG, "LIST_VIEW_UPDATE_MESSAGE; ");
|
||||
}
|
||||
|
||||
mChooserMultiProfilePagerAdapter.getActiveListAdapter().refreshListView();
|
||||
UserHandle userHandle = (UserHandle) msg.obj;
|
||||
mChooserMultiProfilePagerAdapter.getListAdapterForUserHandle(userHandle)
|
||||
.refreshListView();
|
||||
break;
|
||||
|
||||
case SHORTCUT_MANAGER_SHARE_TARGET_RESULT:
|
||||
if (DEBUG) Log.d(TAG, "SHORTCUT_MANAGER_SHARE_TARGET_RESULT");
|
||||
final ServiceResultInfo resultInfo = (ServiceResultInfo) msg.obj;
|
||||
if (resultInfo.resultTargets != null) {
|
||||
mChooserMultiProfilePagerAdapter.getActiveListAdapter().addServiceResults(
|
||||
resultInfo.originalTarget, resultInfo.resultTargets, msg.arg1);
|
||||
ChooserListAdapter adapterForUserHandle =
|
||||
mChooserMultiProfilePagerAdapter.getListAdapterForUserHandle(
|
||||
resultInfo.userHandle);
|
||||
if (adapterForUserHandle != null) {
|
||||
adapterForUserHandle.addServiceResults(
|
||||
resultInfo.originalTarget, resultInfo.resultTargets, msg.arg1,
|
||||
mDirectShareShortcutInfoCache);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -638,45 +652,6 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
.addTaggedData(MetricsEvent.FIELD_SHARESHEET_MIMETYPE, target.getType())
|
||||
.addTaggedData(MetricsEvent.FIELD_TIME_TO_APP_TARGETS, systemCost));
|
||||
|
||||
AppPredictor appPredictor = getAppPredictorForDirectShareIfEnabled();
|
||||
if (appPredictor != null) {
|
||||
mDirectShareAppTargetCache = new HashMap<>();
|
||||
mAppPredictorCallback = resultList -> {
|
||||
//TODO(arangelov) Take care of edge case when callback called after swiping tabs
|
||||
if (isFinishing() || isDestroyed()) {
|
||||
return;
|
||||
}
|
||||
if (mChooserMultiProfilePagerAdapter.getActiveListAdapter().getCount() == 0) {
|
||||
return;
|
||||
}
|
||||
if (resultList.isEmpty()) {
|
||||
// APS may be disabled, so try querying targets ourselves.
|
||||
//TODO(arangelov) queryDirectShareTargets indirectly uses mIntents.
|
||||
// Investigate implications for work tab.
|
||||
queryDirectShareTargets(
|
||||
mChooserMultiProfilePagerAdapter.getActiveListAdapter(), true);
|
||||
return;
|
||||
}
|
||||
final List<DisplayResolveInfo> driList =
|
||||
getDisplayResolveInfos(
|
||||
mChooserMultiProfilePagerAdapter.getActiveListAdapter());
|
||||
final List<ShortcutManager.ShareShortcutInfo> shareShortcutInfos =
|
||||
new ArrayList<>();
|
||||
for (AppTarget appTarget : resultList) {
|
||||
if (appTarget.getShortcutInfo() == null) {
|
||||
continue;
|
||||
}
|
||||
shareShortcutInfos.add(new ShortcutManager.ShareShortcutInfo(
|
||||
appTarget.getShortcutInfo(),
|
||||
new ComponentName(
|
||||
appTarget.getPackageName(), appTarget.getClassName())));
|
||||
}
|
||||
sendShareShortcutInfoList(shareShortcutInfos, driList, resultList);
|
||||
};
|
||||
appPredictor
|
||||
.registerPredictionUpdates(this.getMainExecutor(), mAppPredictorCallback);
|
||||
}
|
||||
|
||||
mChooserRowServiceSpacing = getResources()
|
||||
.getDimensionPixelSize(R.dimen.chooser_service_spacing);
|
||||
|
||||
@@ -707,6 +682,54 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "System Time Cost is " + systemCost);
|
||||
}
|
||||
|
||||
mDirectShareShortcutInfoCache = new HashMap<>();
|
||||
}
|
||||
|
||||
private AppPredictor setupAppPredictorForUser(UserHandle userHandle,
|
||||
AppPredictor.Callback appPredictorCallback) {
|
||||
AppPredictor appPredictor = getAppPredictorForDirectShareIfEnabled(userHandle);
|
||||
if (appPredictor == null) {
|
||||
return null;
|
||||
}
|
||||
mDirectShareAppTargetCache = new HashMap<>();
|
||||
appPredictor.registerPredictionUpdates(this.getMainExecutor(), appPredictorCallback);
|
||||
return appPredictor;
|
||||
}
|
||||
|
||||
private AppPredictor.Callback createAppPredictorCallback(
|
||||
ChooserListAdapter chooserListAdapter) {
|
||||
return resultList -> {
|
||||
//TODO(arangelov) Take care of edge case when callback called after swiping tabs
|
||||
if (isFinishing() || isDestroyed()) {
|
||||
return;
|
||||
}
|
||||
if (chooserListAdapter.getCount() == 0) {
|
||||
return;
|
||||
}
|
||||
if (resultList.isEmpty()) {
|
||||
// APS may be disabled, so try querying targets ourselves.
|
||||
//TODO(arangelov) queryDirectShareTargets indirectly uses mIntents.
|
||||
// Investigate implications for work tab.
|
||||
queryDirectShareTargets(chooserListAdapter, true);
|
||||
return;
|
||||
}
|
||||
final List<DisplayResolveInfo> driList =
|
||||
getDisplayResolveInfos(chooserListAdapter);
|
||||
final List<ShortcutManager.ShareShortcutInfo> shareShortcutInfos =
|
||||
new ArrayList<>();
|
||||
for (AppTarget appTarget : resultList) {
|
||||
if (appTarget.getShortcutInfo() == null) {
|
||||
continue;
|
||||
}
|
||||
shareShortcutInfos.add(new ShortcutManager.ShareShortcutInfo(
|
||||
appTarget.getShortcutInfo(),
|
||||
new ComponentName(
|
||||
appTarget.getPackageName(), appTarget.getClassName())));
|
||||
}
|
||||
sendShareShortcutInfoList(shareShortcutInfos, driList, resultList,
|
||||
chooserListAdapter.getUserHandle());
|
||||
};
|
||||
}
|
||||
|
||||
static SharedPreferences getPinnedSharedPrefs(Context context) {
|
||||
@@ -1260,9 +1283,9 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
|
||||
if (mPreviewCoord != null) mPreviewCoord.cancelLoads();
|
||||
|
||||
if (mAppPredictor != null) {
|
||||
mAppPredictor.unregisterPredictionUpdates(mAppPredictorCallback);
|
||||
mAppPredictor.destroy();
|
||||
mChooserMultiProfilePagerAdapter.getActiveListAdapter().destroyAppPredictor();
|
||||
if (mChooserMultiProfilePagerAdapter.getInactiveListAdapter() != null) {
|
||||
mChooserMultiProfilePagerAdapter.getInactiveListAdapter().destroyAppPredictor();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1312,7 +1335,8 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
mChooserMultiProfilePagerAdapter.getActiveListAdapter().addServiceResults(
|
||||
/* origTarget */ null,
|
||||
Lists.newArrayList(mCallerChooserTargets),
|
||||
TARGET_TYPE_DEFAULT);
|
||||
TARGET_TYPE_DEFAULT,
|
||||
/* directShareShortcutInfoCache */ null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1541,8 +1565,10 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
void queryTargetServices(ChooserListAdapter adapter) {
|
||||
mQueriedTargetServicesTimeMs = System.currentTimeMillis();
|
||||
|
||||
final PackageManager pm = getPackageManager();
|
||||
ShortcutManager sm = (ShortcutManager) getSystemService(ShortcutManager.class);
|
||||
Context selectedProfileContext = createContextAsUser(
|
||||
adapter.getUserHandle(), 0 /* flags */);
|
||||
final PackageManager pm = selectedProfileContext.getPackageManager();
|
||||
ShortcutManager sm = selectedProfileContext.getSystemService(ShortcutManager.class);
|
||||
int targetsToQuery = 0;
|
||||
|
||||
for (int i = 0, N = adapter.getDisplayResolveInfoCount(); i < N; i++) {
|
||||
@@ -1565,10 +1591,13 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
final ComponentName serviceComponent = new ComponentName(
|
||||
ai.packageName, serviceName);
|
||||
|
||||
if (mServicesRequested.contains(serviceComponent)) {
|
||||
UserHandle userHandle = adapter.getUserHandle();
|
||||
Pair<ComponentName, UserHandle> requestedItem =
|
||||
new Pair<>(serviceComponent, userHandle);
|
||||
if (mServicesRequested.contains(requestedItem)) {
|
||||
continue;
|
||||
}
|
||||
mServicesRequested.add(serviceComponent);
|
||||
mServicesRequested.add(requestedItem);
|
||||
|
||||
final Intent serviceIntent = new Intent(ChooserTargetService.SERVICE_INTERFACE)
|
||||
.setComponent(serviceComponent);
|
||||
@@ -1596,13 +1625,14 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
}
|
||||
|
||||
final ChooserTargetServiceConnection conn =
|
||||
new ChooserTargetServiceConnection(this, dri);
|
||||
new ChooserTargetServiceConnection(this, dri,
|
||||
adapter.getUserHandle());
|
||||
|
||||
// Explicitly specify Process.myUserHandle instead of calling bindService
|
||||
// Explicitly specify the user handle instead of calling bindService
|
||||
// to avoid the warning from calling from the system process without an explicit
|
||||
// user handle
|
||||
if (bindServiceAsUser(serviceIntent, conn, BIND_AUTO_CREATE | BIND_NOT_FOREGROUND,
|
||||
Process.myUserHandle())) {
|
||||
adapter.getUserHandle())) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Binding service connection for target " + dri
|
||||
+ " intent " + serviceIntent);
|
||||
@@ -1684,8 +1714,9 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
private void queryDirectShareTargets(
|
||||
ChooserListAdapter adapter, boolean skipAppPredictionService) {
|
||||
mQueriedSharingShortcutsTimeMs = System.currentTimeMillis();
|
||||
UserHandle userHandle = adapter.getUserHandle();
|
||||
if (!skipAppPredictionService) {
|
||||
AppPredictor appPredictor = getAppPredictorForDirectShareIfEnabled();
|
||||
AppPredictor appPredictor = getAppPredictorForDirectShareIfEnabled(userHandle);
|
||||
if (appPredictor != null) {
|
||||
appPredictor.requestPredictionUpdate();
|
||||
return;
|
||||
@@ -1700,17 +1731,18 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
final List<DisplayResolveInfo> driList = getDisplayResolveInfos(adapter);
|
||||
|
||||
AsyncTask.execute(() -> {
|
||||
//TODO(arangelov) use the selected probile tab's ShortcutManager
|
||||
ShortcutManager sm = (ShortcutManager) getSystemService(Context.SHORTCUT_SERVICE);
|
||||
Context selectedProfileContext = createContextAsUser(userHandle, 0 /* flags */);
|
||||
ShortcutManager sm = (ShortcutManager) selectedProfileContext
|
||||
.getSystemService(Context.SHORTCUT_SERVICE);
|
||||
List<ShortcutManager.ShareShortcutInfo> resultList = sm.getShareTargets(filter);
|
||||
sendShareShortcutInfoList(resultList, driList, null);
|
||||
sendShareShortcutInfoList(resultList, driList, null, userHandle);
|
||||
});
|
||||
}
|
||||
|
||||
private void sendShareShortcutInfoList(
|
||||
List<ShortcutManager.ShareShortcutInfo> resultList,
|
||||
List<DisplayResolveInfo> driList,
|
||||
@Nullable List<AppTarget> appTargets) {
|
||||
@Nullable List<AppTarget> appTargets, UserHandle userHandle) {
|
||||
if (appTargets != null && appTargets.size() != resultList.size()) {
|
||||
throw new RuntimeException("resultList and appTargets must have the same size."
|
||||
+ " resultList.size()=" + resultList.size()
|
||||
@@ -1749,9 +1781,11 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
List<ChooserTarget> chooserTargets = convertToChooserTarget(
|
||||
matchingShortcuts, resultList, appTargets, shortcutType);
|
||||
|
||||
|
||||
|
||||
final Message msg = Message.obtain();
|
||||
msg.what = ChooserHandler.SHORTCUT_MANAGER_SHARE_TARGET_RESULT;
|
||||
msg.obj = new ServiceResultInfo(driList.get(i), chooserTargets, null);
|
||||
msg.obj = new ServiceResultInfo(driList.get(i), chooserTargets, null, userHandle);
|
||||
msg.arg1 = shortcutType;
|
||||
mChooserHandler.sendMessage(msg);
|
||||
resultMessageSent = true;
|
||||
@@ -1842,6 +1876,9 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
mDirectShareAppTargetCache.put(chooserTarget,
|
||||
allAppTargets.get(indexInAllShortcuts));
|
||||
}
|
||||
if (mDirectShareShortcutInfoCache != null) {
|
||||
mDirectShareShortcutInfoCache.put(chooserTarget, shortcutInfo);
|
||||
}
|
||||
}
|
||||
// Sort ChooserTargets by score in descending order
|
||||
Comparator<ChooserTarget> byScore =
|
||||
@@ -1915,7 +1952,8 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
}
|
||||
|
||||
private void sendClickToAppPredictor(TargetInfo targetInfo) {
|
||||
AppPredictor directShareAppPredictor = getAppPredictorForDirectShareIfEnabled();
|
||||
AppPredictor directShareAppPredictor = getAppPredictorForDirectShareIfEnabled(
|
||||
mChooserMultiProfilePagerAdapter.getCurrentUserHandle());
|
||||
if (directShareAppPredictor == null) {
|
||||
return;
|
||||
}
|
||||
@@ -1937,34 +1975,54 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private AppPredictor getAppPredictor() {
|
||||
private AppPredictor createAppPredictor(UserHandle userHandle) {
|
||||
if (!mIsAppPredictorComponentAvailable) {
|
||||
return null;
|
||||
}
|
||||
if (mAppPredictor == null) {
|
||||
final IntentFilter filter = getTargetIntentFilter();
|
||||
Bundle extras = new Bundle();
|
||||
extras.putParcelable(APP_PREDICTION_INTENT_FILTER_KEY, filter);
|
||||
AppPredictionContext appPredictionContext = new AppPredictionContext.Builder(this)
|
||||
.setUiSurface(APP_PREDICTION_SHARE_UI_SURFACE)
|
||||
.setPredictedTargetCount(APP_PREDICTION_SHARE_TARGET_QUERY_PACKAGE_LIMIT)
|
||||
.setExtras(extras)
|
||||
.build();
|
||||
AppPredictionManager appPredictionManager
|
||||
= getSystemService(AppPredictionManager.class);
|
||||
mAppPredictor = appPredictionManager.createAppPredictionSession(appPredictionContext);
|
||||
|
||||
if (getPersonalProfileUserHandle() == userHandle) {
|
||||
if (mPersonalAppPredictor != null) {
|
||||
return mPersonalAppPredictor;
|
||||
}
|
||||
} else {
|
||||
if (mWorkAppPredictor != null) {
|
||||
return mWorkAppPredictor;
|
||||
}
|
||||
}
|
||||
return mAppPredictor;
|
||||
|
||||
// TODO(b/148230574): Currently AppPredictor fetches only the same-profile app targets.
|
||||
// Make AppPredictor work cross-profile.
|
||||
Context contextAsUser = createContextAsUser(userHandle, 0 /* flags */);
|
||||
final IntentFilter filter = getTargetIntentFilter();
|
||||
Bundle extras = new Bundle();
|
||||
extras.putParcelable(APP_PREDICTION_INTENT_FILTER_KEY, filter);
|
||||
AppPredictionContext appPredictionContext = new AppPredictionContext.Builder(contextAsUser)
|
||||
.setUiSurface(APP_PREDICTION_SHARE_UI_SURFACE)
|
||||
.setPredictedTargetCount(APP_PREDICTION_SHARE_TARGET_QUERY_PACKAGE_LIMIT)
|
||||
.setExtras(extras)
|
||||
.build();
|
||||
AppPredictionManager appPredictionManager =
|
||||
contextAsUser
|
||||
.getSystemService(AppPredictionManager.class);
|
||||
AppPredictor appPredictionSession = appPredictionManager.createAppPredictionSession(
|
||||
appPredictionContext);
|
||||
if (getPersonalProfileUserHandle() == userHandle) {
|
||||
mPersonalAppPredictor = appPredictionSession;
|
||||
} else {
|
||||
mWorkAppPredictor = appPredictionSession;
|
||||
}
|
||||
return appPredictionSession;
|
||||
}
|
||||
|
||||
/**
|
||||
* This will return an app predictor if it is enabled for direct share sorting
|
||||
* and if one exists. Otherwise, it returns null.
|
||||
* @param userHandle
|
||||
*/
|
||||
@Nullable
|
||||
private AppPredictor getAppPredictorForDirectShareIfEnabled() {
|
||||
private AppPredictor getAppPredictorForDirectShareIfEnabled(UserHandle userHandle) {
|
||||
return ChooserFlags.USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS
|
||||
&& !ActivityManager.isLowRamDeviceStatic() ? getAppPredictor() : null;
|
||||
&& !ActivityManager.isLowRamDeviceStatic() ? createAppPredictor(userHandle) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1972,8 +2030,8 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
* and if one exists. Otherwise, it returns null.
|
||||
*/
|
||||
@Nullable
|
||||
private AppPredictor getAppPredictorForShareActivitesIfEnabled() {
|
||||
return USE_PREDICTION_MANAGER_FOR_SHARE_ACTIVITIES ? getAppPredictor() : null;
|
||||
private AppPredictor getAppPredictorForShareActivitiesIfEnabled(UserHandle userHandle) {
|
||||
return USE_PREDICTION_MANAGER_FOR_SHARE_ACTIVITIES ? createAppPredictor(userHandle) : null;
|
||||
}
|
||||
|
||||
void onRefinementResult(TargetInfo selectedTarget, Intent matchingIntent) {
|
||||
@@ -2016,12 +2074,13 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
return false;
|
||||
}
|
||||
|
||||
void filterServiceTargets(String packageName, List<ChooserTarget> targets) {
|
||||
void filterServiceTargets(Context contextAsUser, String packageName,
|
||||
List<ChooserTarget> targets) {
|
||||
if (targets == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final PackageManager pm = getPackageManager();
|
||||
final PackageManager pm = contextAsUser.getPackageManager();
|
||||
for (int i = targets.size() - 1; i >= 0; i--) {
|
||||
final ChooserTarget target = targets.get(i);
|
||||
final ComponentName targetName = target.getComponentName();
|
||||
@@ -2104,19 +2163,24 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
public ChooserGridAdapter createChooserGridAdapter(Context context,
|
||||
List<Intent> payloadIntents, Intent[] initialIntents, List<ResolveInfo> rList,
|
||||
boolean filterLastUsed, boolean useLayoutForBrowsables, UserHandle userHandle) {
|
||||
return new ChooserGridAdapter(
|
||||
new ChooserListAdapter(context, payloadIntents, initialIntents, rList,
|
||||
filterLastUsed, createListController(userHandle), useLayoutForBrowsables,
|
||||
this, this));
|
||||
ChooserListAdapter chooserListAdapter = new ChooserListAdapter(context, payloadIntents,
|
||||
initialIntents, rList,
|
||||
filterLastUsed, createListController(userHandle), useLayoutForBrowsables,
|
||||
this, this);
|
||||
AppPredictor.Callback appPredictorCallback = createAppPredictorCallback(chooserListAdapter);
|
||||
AppPredictor appPredictor = setupAppPredictorForUser(userHandle, appPredictorCallback);
|
||||
chooserListAdapter.setAppPredictor(appPredictor);
|
||||
chooserListAdapter.setAppPredictorCallback(appPredictorCallback);
|
||||
return new ChooserGridAdapter(chooserListAdapter);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected ResolverListController createListController(UserHandle userHandle) {
|
||||
AppPredictor appPredictor = getAppPredictorForShareActivitesIfEnabled();
|
||||
AppPredictor appPredictor = getAppPredictorForShareActivitiesIfEnabled(userHandle);
|
||||
AbstractResolverComparator resolverComparator;
|
||||
if (appPredictor != null) {
|
||||
resolverComparator = new AppPredictionServiceResolverComparator(this, getTargetIntent(),
|
||||
getReferrerPackageName(), appPredictor, getUser());
|
||||
getReferrerPackageName(), appPredictor, userHandle);
|
||||
} else {
|
||||
resolverComparator =
|
||||
new ResolverRankerServiceResolverComparator(this, getTargetIntent(),
|
||||
@@ -2297,9 +2361,11 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
}
|
||||
|
||||
@Override // ChooserListCommunicator
|
||||
public void sendListViewUpdateMessage() {
|
||||
mChooserHandler.sendEmptyMessageDelayed(ChooserHandler.LIST_VIEW_UPDATE_MESSAGE,
|
||||
LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS);
|
||||
public void sendListViewUpdateMessage(UserHandle userHandle) {
|
||||
Message msg = Message.obtain();
|
||||
msg.what = ChooserHandler.LIST_VIEW_UPDATE_MESSAGE;
|
||||
msg.obj = userHandle;
|
||||
mChooserHandler.sendMessageDelayed(msg, LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -3158,6 +3224,7 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
private DisplayResolveInfo mOriginalTarget;
|
||||
private ComponentName mConnectedComponent;
|
||||
private ChooserActivity mChooserActivity;
|
||||
private final UserHandle mUserHandle;
|
||||
private final Object mLock = new Object();
|
||||
|
||||
private final IChooserTargetResult mChooserTargetResult = new IChooserTargetResult.Stub() {
|
||||
@@ -3169,21 +3236,24 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
+ mConnectedComponent + "; ignoring...");
|
||||
return;
|
||||
}
|
||||
mChooserActivity.filterServiceTargets(
|
||||
Context contextAsUser =
|
||||
mChooserActivity.createContextAsUser(mUserHandle, 0 /* flags */);
|
||||
mChooserActivity.filterServiceTargets(contextAsUser,
|
||||
mOriginalTarget.getResolveInfo().activityInfo.packageName, targets);
|
||||
final Message msg = Message.obtain();
|
||||
msg.what = ChooserHandler.CHOOSER_TARGET_SERVICE_RESULT;
|
||||
msg.obj = new ServiceResultInfo(mOriginalTarget, targets,
|
||||
ChooserTargetServiceConnection.this);
|
||||
ChooserTargetServiceConnection.this, mUserHandle);
|
||||
mChooserActivity.mChooserHandler.sendMessage(msg);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public ChooserTargetServiceConnection(ChooserActivity chooserActivity,
|
||||
DisplayResolveInfo dri) {
|
||||
DisplayResolveInfo dri, UserHandle userHandle) {
|
||||
mChooserActivity = chooserActivity;
|
||||
mOriginalTarget = dri;
|
||||
mUserHandle = userHandle;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -3249,12 +3319,14 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
public final DisplayResolveInfo originalTarget;
|
||||
public final List<ChooserTarget> resultTargets;
|
||||
public final ChooserTargetServiceConnection connection;
|
||||
public final UserHandle userHandle;
|
||||
|
||||
public ServiceResultInfo(DisplayResolveInfo ot, List<ChooserTarget> rt,
|
||||
ChooserTargetServiceConnection c) {
|
||||
ChooserTargetServiceConnection c, UserHandle userHandle) {
|
||||
originalTarget = ot;
|
||||
resultTargets = rt;
|
||||
connection = c;
|
||||
this.userHandle = userHandle;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,9 @@ package com.android.internal.app;
|
||||
import static com.android.internal.app.ChooserActivity.TARGET_TYPE_SHORTCUTS_FROM_PREDICTION_SERVICE;
|
||||
import static com.android.internal.app.ChooserActivity.TARGET_TYPE_SHORTCUTS_FROM_SHORTCUT_MANAGER;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.prediction.AppPredictor;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -27,7 +29,9 @@ import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.LabeledIntent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.ShortcutInfo;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.service.chooser.ChooserTarget;
|
||||
import android.util.Log;
|
||||
@@ -90,6 +94,8 @@ public class ChooserListAdapter extends ResolverListAdapter {
|
||||
|
||||
// Sorted list of DisplayResolveInfos for the alphabetical app section.
|
||||
private List<DisplayResolveInfo> mSortedList = new ArrayList<>();
|
||||
private AppPredictor mAppPredictor;
|
||||
private AppPredictor.Callback mAppPredictorCallback;
|
||||
|
||||
public ChooserListAdapter(Context context, List<Intent> payloadIntents,
|
||||
Intent[] initialIntents, List<ResolveInfo> rList,
|
||||
@@ -160,6 +166,10 @@ public class ChooserListAdapter extends ResolverListAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
AppPredictor getAppPredictor() {
|
||||
return mAppPredictor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handlePackagesChanged() {
|
||||
if (DEBUG) {
|
||||
@@ -173,7 +183,7 @@ public class ChooserListAdapter extends ResolverListAdapter {
|
||||
@Override
|
||||
public void notifyDataSetChanged() {
|
||||
if (!mListViewDataChanged) {
|
||||
mChooserListCommunicator.sendListViewUpdateMessage();
|
||||
mChooserListCommunicator.sendListViewUpdateMessage(getUserHandle());
|
||||
mListViewDataChanged = true;
|
||||
}
|
||||
}
|
||||
@@ -383,7 +393,8 @@ public class ChooserListAdapter extends ResolverListAdapter {
|
||||
* if score is too low.
|
||||
*/
|
||||
public void addServiceResults(DisplayResolveInfo origTarget, List<ChooserTarget> targets,
|
||||
@ChooserActivity.ShareTargetType int targetType) {
|
||||
@ChooserActivity.ShareTargetType int targetType,
|
||||
Map<ChooserTarget, ShortcutInfo> directShareToShortcutInfos) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "addServiceResults " + origTarget + ", " + targets.size()
|
||||
+ " targets");
|
||||
@@ -412,8 +423,11 @@ public class ChooserListAdapter extends ResolverListAdapter {
|
||||
// This incents ChooserTargetServices to define what's truly better.
|
||||
targetScore = lastScore * 0.95f;
|
||||
}
|
||||
boolean isInserted = insertServiceTarget(new SelectableTargetInfo(
|
||||
mContext, origTarget, target, targetScore, mSelectableTargetInfoComunicator));
|
||||
UserHandle userHandle = getUserHandle();
|
||||
Context contextAsUser = mContext.createContextAsUser(userHandle, 0 /* flags */);
|
||||
boolean isInserted = insertServiceTarget(new SelectableTargetInfo(contextAsUser,
|
||||
origTarget, target, targetScore, mSelectableTargetInfoComunicator,
|
||||
(isShortcutResult ? directShareToShortcutInfos.get(target) : null)));
|
||||
|
||||
if (isInserted && isShortcutResult) {
|
||||
mNumShortcutResults++;
|
||||
@@ -547,6 +561,21 @@ public class ChooserListAdapter extends ResolverListAdapter {
|
||||
};
|
||||
}
|
||||
|
||||
public void setAppPredictor(AppPredictor appPredictor) {
|
||||
mAppPredictor = appPredictor;
|
||||
}
|
||||
|
||||
public void setAppPredictorCallback(AppPredictor.Callback appPredictorCallback) {
|
||||
mAppPredictorCallback = appPredictorCallback;
|
||||
}
|
||||
|
||||
public void destroyAppPredictor() {
|
||||
if (getAppPredictor() != null) {
|
||||
getAppPredictor().unregisterPredictionUpdates(mAppPredictorCallback);
|
||||
getAppPredictor().destroy();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Necessary methods to communicate between {@link ChooserListAdapter}
|
||||
* and {@link ChooserActivity}.
|
||||
@@ -555,7 +584,7 @@ public class ChooserListAdapter extends ResolverListAdapter {
|
||||
|
||||
int getMaxRankedTargets();
|
||||
|
||||
void sendListViewUpdateMessage();
|
||||
void sendListViewUpdateMessage(UserHandle userHandle);
|
||||
|
||||
boolean isSendAction(Intent targetIntent);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.internal.app;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.os.UserHandle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
@@ -83,6 +84,18 @@ public class ChooserMultiProfilePagerAdapter extends AbstractMultiProfilePagerAd
|
||||
return mItems[pageIndex].chooserGridAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
ChooserListAdapter getListAdapterForUserHandle(UserHandle userHandle) {
|
||||
if (getActiveListAdapter().getUserHandle() == userHandle) {
|
||||
return getActiveListAdapter();
|
||||
} else if (getInactiveListAdapter() != null
|
||||
&& getInactiveListAdapter().getUserHandle() == userHandle) {
|
||||
return getInactiveListAdapter();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setupListAdapter(int pageIndex) {
|
||||
final RecyclerView recyclerView = getItem(pageIndex).recyclerView;
|
||||
|
||||
@@ -543,6 +543,9 @@ public class ResolverActivity extends Activity implements
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
mMultiProfilePagerAdapter.getActiveListAdapter().handlePackagesChanged();
|
||||
if (mMultiProfilePagerAdapter.getInactiveListAdapter() != null) {
|
||||
mMultiProfilePagerAdapter.getInactiveListAdapter().handlePackagesChanged();
|
||||
}
|
||||
|
||||
if (mSystemWindowInsets != null) {
|
||||
mResolverDrawerLayout.setPadding(mSystemWindowInsets.left, mSystemWindowInsets.top,
|
||||
|
||||
@@ -407,6 +407,7 @@ public class ResolverListAdapter extends BaseAdapter {
|
||||
// We assume that at this point we've already filtered out the only intent for a different
|
||||
// targetUserId which we're going to use.
|
||||
private void addResolveInfo(DisplayResolveInfo dri) {
|
||||
// TODO(arangelov): Is that UserHandle.USER_CURRENT check okay?
|
||||
if (dri != null && dri.getResolveInfo() != null
|
||||
&& dri.getResolveInfo().targetUserId == UserHandle.USER_CURRENT) {
|
||||
// Checks if this info is already listed in display.
|
||||
@@ -575,7 +576,7 @@ public class ResolverListAdapter extends BaseAdapter {
|
||||
|
||||
Drawable loadIconForResolveInfo(ResolveInfo ri) {
|
||||
// Load icons based on the current process. If in work profile icons should be badged.
|
||||
return makePresentationGetter(ri).getIcon(mResolverListController.getUserHandle());
|
||||
return makePresentationGetter(ri).getIcon(getUserHandle());
|
||||
}
|
||||
|
||||
void loadFilteredItemIconTaskAsync(@NonNull ImageView iconView) {
|
||||
@@ -585,6 +586,10 @@ public class ResolverListAdapter extends BaseAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
UserHandle getUserHandle() {
|
||||
return mResolverListController.getUserHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Necessary methods to communicate between {@link ResolverListAdapter}
|
||||
* and {@link ResolverActivity}.
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.internal.app;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.os.UserHandle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ListView;
|
||||
@@ -87,6 +88,18 @@ public class ResolverMultiProfilePagerAdapter extends AbstractMultiProfilePagerA
|
||||
return mItems[pageIndex].resolverListAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
ResolverListAdapter getListAdapterForUserHandle(UserHandle userHandle) {
|
||||
if (getActiveListAdapter().getUserHandle() == userHandle) {
|
||||
return getActiveListAdapter();
|
||||
} else if (getInactiveListAdapter() != null
|
||||
&& getInactiveListAdapter().getUserHandle() == userHandle) {
|
||||
return getInactiveListAdapter();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@VisibleForTesting
|
||||
public ResolverListAdapter getActiveListAdapter() {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.internal.app.chooser;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.Activity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
@@ -70,7 +71,8 @@ public final class SelectableTargetInfo implements ChooserTargetInfo {
|
||||
|
||||
public SelectableTargetInfo(Context context, DisplayResolveInfo sourceInfo,
|
||||
ChooserTarget chooserTarget,
|
||||
float modifiedScore, SelectableTargetInfoCommunicator selectableTargetInfoComunicator) {
|
||||
float modifiedScore, SelectableTargetInfoCommunicator selectableTargetInfoComunicator,
|
||||
@Nullable ShortcutInfo shortcutInfo) {
|
||||
mContext = context;
|
||||
mSourceInfo = sourceInfo;
|
||||
mChooserTarget = chooserTarget;
|
||||
@@ -91,7 +93,7 @@ public final class SelectableTargetInfo implements ChooserTargetInfo {
|
||||
}
|
||||
}
|
||||
// TODO(b/121287224): do this in the background thread, and only for selected targets
|
||||
mDisplayIcon = getChooserTargetIconDrawable(chooserTarget);
|
||||
mDisplayIcon = getChooserTargetIconDrawable(chooserTarget, shortcutInfo);
|
||||
|
||||
if (sourceInfo != null) {
|
||||
mBackupResolveInfo = null;
|
||||
@@ -134,34 +136,18 @@ public final class SelectableTargetInfo implements ChooserTargetInfo {
|
||||
return mIsSuspended;
|
||||
}
|
||||
|
||||
/**
|
||||
* Since ShortcutInfos are returned by ShortcutManager, we can cache the shortcuts and skip
|
||||
* the call to LauncherApps#getShortcuts(ShortcutQuery).
|
||||
*/
|
||||
// TODO(121287224): Refactor code to apply the suggestion above
|
||||
private Drawable getChooserTargetIconDrawable(ChooserTarget target) {
|
||||
private Drawable getChooserTargetIconDrawable(ChooserTarget target,
|
||||
@Nullable ShortcutInfo shortcutInfo) {
|
||||
Drawable directShareIcon = null;
|
||||
|
||||
// First get the target drawable and associated activity info
|
||||
final Icon icon = target.getIcon();
|
||||
if (icon != null) {
|
||||
directShareIcon = icon.loadDrawable(mContext);
|
||||
} else if (ChooserFlags.USE_SHORTCUT_MANAGER_FOR_DIRECT_TARGETS) {
|
||||
Bundle extras = target.getIntentExtras();
|
||||
if (extras != null && extras.containsKey(Intent.EXTRA_SHORTCUT_ID)) {
|
||||
CharSequence shortcutId = extras.getCharSequence(Intent.EXTRA_SHORTCUT_ID);
|
||||
LauncherApps launcherApps = (LauncherApps) mContext.getSystemService(
|
||||
Context.LAUNCHER_APPS_SERVICE);
|
||||
final LauncherApps.ShortcutQuery q = new LauncherApps.ShortcutQuery();
|
||||
q.setPackage(target.getComponentName().getPackageName());
|
||||
q.setShortcutIds(Arrays.asList(shortcutId.toString()));
|
||||
q.setQueryFlags(LauncherApps.ShortcutQuery.FLAG_MATCH_DYNAMIC);
|
||||
final List<ShortcutInfo> shortcuts =
|
||||
launcherApps.getShortcuts(q, mContext.getUser());
|
||||
if (shortcuts != null && shortcuts.size() > 0) {
|
||||
directShareIcon = launcherApps.getShortcutIconDrawable(shortcuts.get(0), 0);
|
||||
}
|
||||
}
|
||||
} else if (ChooserFlags.USE_SHORTCUT_MANAGER_FOR_DIRECT_TARGETS && shortcutInfo != null) {
|
||||
LauncherApps launcherApps = (LauncherApps) mContext.getSystemService(
|
||||
Context.LAUNCHER_APPS_SERVICE);
|
||||
directShareIcon = launcherApps.getShortcutIconDrawable(shortcutInfo, 0);
|
||||
}
|
||||
|
||||
if (directShareIcon == null) return null;
|
||||
|
||||
Reference in New Issue
Block a user