Merge changes I0677bca4,I7cad6529
* changes: Fix autolaunching. Create a PackageMonitor instance for each profile.
This commit is contained in:
committed by
Android (Google) Code Review
commit
653dd7b19f
@@ -18,7 +18,9 @@ package com.android.internal.app;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
@@ -27,6 +29,7 @@ import com.android.internal.widget.PagerAdapter;
|
||||
import com.android.internal.widget.ViewPager;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -46,11 +49,17 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter {
|
||||
private int mCurrentPage;
|
||||
private OnProfileSelectedListener mOnProfileSelectedListener;
|
||||
private Set<Integer> mLoadedPages;
|
||||
private final UserHandle mPersonalProfileUserHandle;
|
||||
private final UserHandle mWorkProfileUserHandle;
|
||||
|
||||
AbstractMultiProfilePagerAdapter(Context context, int currentPage) {
|
||||
AbstractMultiProfilePagerAdapter(Context context, int currentPage,
|
||||
UserHandle personalProfileUserHandle,
|
||||
UserHandle workProfileUserHandle) {
|
||||
mContext = Objects.requireNonNull(context);
|
||||
mCurrentPage = currentPage;
|
||||
mLoadedPages = new HashSet<>();
|
||||
mPersonalProfileUserHandle = personalProfileUserHandle;
|
||||
mWorkProfileUserHandle = workProfileUserHandle;
|
||||
}
|
||||
|
||||
void setOnProfileSelectedListener(OnProfileSelectedListener listener) {
|
||||
@@ -72,7 +81,7 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter {
|
||||
public void onPageSelected(int position) {
|
||||
mCurrentPage = position;
|
||||
if (!mLoadedPages.contains(position)) {
|
||||
getActiveListAdapter().rebuildList();
|
||||
rebuildActiveTab(true);
|
||||
mLoadedPages.add(position);
|
||||
}
|
||||
if (mOnProfileSelectedListener != null) {
|
||||
@@ -85,6 +94,13 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter {
|
||||
mLoadedPages.add(mCurrentPage);
|
||||
}
|
||||
|
||||
void clearInactiveProfileCache() {
|
||||
if (mLoadedPages.size() == 1) {
|
||||
return;
|
||||
}
|
||||
mLoadedPages.remove(1 - mCurrentPage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewGroup instantiateItem(ViewGroup container, int position) {
|
||||
final ProfileDescriptor profileDescriptor = getItem(position);
|
||||
@@ -187,12 +203,53 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter {
|
||||
@VisibleForTesting
|
||||
public abstract @Nullable ResolverListAdapter getInactiveListAdapter();
|
||||
|
||||
public abstract ResolverListAdapter getPersonalListAdapter();
|
||||
|
||||
public abstract @Nullable ResolverListAdapter getWorkListAdapter();
|
||||
|
||||
abstract Object getCurrentRootAdapter();
|
||||
|
||||
abstract ViewGroup getActiveAdapterView();
|
||||
|
||||
abstract @Nullable ViewGroup getInactiveAdapterView();
|
||||
|
||||
boolean rebuildActiveTab(boolean post) {
|
||||
return rebuildTab(getActiveListAdapter(), post);
|
||||
}
|
||||
|
||||
boolean rebuildInactiveTab(boolean post) {
|
||||
if (getItemCount() == 1) {
|
||||
return false;
|
||||
}
|
||||
return rebuildTab(getInactiveListAdapter(), post);
|
||||
}
|
||||
|
||||
private boolean rebuildTab(ResolverListAdapter activeListAdapter, boolean doPostProcessing) {
|
||||
UserHandle listUserHandle = activeListAdapter.getUserHandle();
|
||||
if (UserHandle.myUserId() != listUserHandle.getIdentifier() &&
|
||||
!hasAppsInOtherProfile(activeListAdapter)) {
|
||||
// TODO(arangelov): Show empty state UX here
|
||||
return false;
|
||||
} else {
|
||||
return activeListAdapter.rebuildList(doPostProcessing);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasAppsInOtherProfile(ResolverListAdapter adapter) {
|
||||
if (mWorkProfileUserHandle == null) {
|
||||
return false;
|
||||
}
|
||||
List<ResolverActivity.ResolvedComponentInfo> resolversForIntent =
|
||||
adapter.getResolversForUser(UserHandle.of(UserHandle.myUserId()));
|
||||
for (ResolverActivity.ResolvedComponentInfo info : resolversForIntent) {
|
||||
ResolveInfo resolveInfo = info.getResolveInfoAt(0);
|
||||
if (resolveInfo.targetUserId != UserHandle.USER_CURRENT) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected class ProfileDescriptor {
|
||||
final ViewGroup rootView;
|
||||
ProfileDescriptor(ViewGroup rootView) {
|
||||
|
||||
@@ -793,7 +793,9 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
/* userHandle */ UserHandle.of(UserHandle.myUserId()));
|
||||
return new ChooserMultiProfilePagerAdapter(
|
||||
/* context */ this,
|
||||
adapter);
|
||||
adapter,
|
||||
getPersonalProfileUserHandle(),
|
||||
/* workProfileUserHandle= */ null);
|
||||
}
|
||||
|
||||
private ChooserMultiProfilePagerAdapter createChooserMultiProfilePagerAdapterForTwoProfiles(
|
||||
@@ -820,7 +822,9 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
/* context */ this,
|
||||
personalAdapter,
|
||||
workAdapter,
|
||||
/* defaultProfile */ getCurrentProfile());
|
||||
/* defaultProfile */ getCurrentProfile(),
|
||||
getPersonalProfileUserHandle(),
|
||||
getWorkProfileUserHandle());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -872,11 +876,11 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PackageMonitor createPackageMonitor() {
|
||||
protected PackageMonitor createPackageMonitor(ResolverListAdapter listAdapter) {
|
||||
return new PackageMonitor() {
|
||||
@Override
|
||||
public void onSomePackagesChanged() {
|
||||
handlePackagesChanged();
|
||||
handlePackagesChanged(listAdapter);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -885,9 +889,19 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
* Update UI to reflect changes in data.
|
||||
*/
|
||||
public void handlePackagesChanged() {
|
||||
// TODO(arangelov): Dispatch this to all adapters when we have the helper methods
|
||||
// in a follow-up CL
|
||||
mChooserMultiProfilePagerAdapter.getActiveListAdapter().handlePackagesChanged();
|
||||
handlePackagesChanged(/* listAdapter */ null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update UI to reflect changes in data.
|
||||
* <p>If {@code listAdapter} is {@code null}, both profile list adapters are updated.
|
||||
*/
|
||||
private void handlePackagesChanged(@Nullable ResolverListAdapter listAdapter) {
|
||||
if (listAdapter == null) {
|
||||
mChooserMultiProfilePagerAdapter.getActiveListAdapter().handlePackagesChanged();
|
||||
} else {
|
||||
listAdapter.handlePackagesChanged();
|
||||
}
|
||||
updateProfileViewButton();
|
||||
}
|
||||
|
||||
@@ -2458,10 +2472,10 @@ public class ChooserActivity extends ResolverActivity implements
|
||||
}
|
||||
|
||||
@Override // ResolverListCommunicator
|
||||
public void onHandlePackagesChanged() {
|
||||
public void onHandlePackagesChanged(ResolverListAdapter listAdapter) {
|
||||
mServicesRequested.clear();
|
||||
mChooserMultiProfilePagerAdapter.getActiveListAdapter().notifyDataSetChanged();
|
||||
super.onHandlePackagesChanged();
|
||||
super.onHandlePackagesChanged(listAdapter);
|
||||
}
|
||||
|
||||
@Override // SelectableTargetInfoCommunicator
|
||||
|
||||
@@ -19,7 +19,6 @@ 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;
|
||||
@@ -176,7 +175,7 @@ public class ChooserListAdapter extends ResolverListAdapter {
|
||||
Log.d(TAG, "clearing queryTargets on package change");
|
||||
}
|
||||
createPlaceHolders();
|
||||
mChooserListCommunicator.onHandlePackagesChanged();
|
||||
mChooserListCommunicator.onHandlePackagesChanged(this);
|
||||
|
||||
}
|
||||
|
||||
@@ -541,7 +540,7 @@ public class ChooserListAdapter extends ResolverListAdapter {
|
||||
@Override
|
||||
AsyncTask<List<ResolvedComponentInfo>,
|
||||
Void,
|
||||
List<ResolvedComponentInfo>> createSortingTask() {
|
||||
List<ResolvedComponentInfo>> createSortingTask(boolean doPostProcessing) {
|
||||
return new AsyncTask<List<ResolvedComponentInfo>,
|
||||
Void,
|
||||
List<ResolvedComponentInfo>>() {
|
||||
@@ -554,9 +553,11 @@ public class ChooserListAdapter extends ResolverListAdapter {
|
||||
}
|
||||
@Override
|
||||
protected void onPostExecute(List<ResolvedComponentInfo> sortedComponents) {
|
||||
processSortedList(sortedComponents);
|
||||
mChooserListCommunicator.updateProfileViewButton();
|
||||
notifyDataSetChanged();
|
||||
processSortedList(sortedComponents, doPostProcessing);
|
||||
if (doPostProcessing) {
|
||||
mChooserListCommunicator.updateProfileViewButton();
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -38,8 +38,10 @@ public class ChooserMultiProfilePagerAdapter extends AbstractMultiProfilePagerAd
|
||||
private final ChooserProfileDescriptor[] mItems;
|
||||
|
||||
ChooserMultiProfilePagerAdapter(Context context,
|
||||
ChooserActivity.ChooserGridAdapter adapter) {
|
||||
super(context, /* currentPage */ 0);
|
||||
ChooserActivity.ChooserGridAdapter adapter,
|
||||
UserHandle personalProfileUserHandle,
|
||||
UserHandle workProfileUserHandle) {
|
||||
super(context, /* currentPage */ 0, personalProfileUserHandle, workProfileUserHandle);
|
||||
mItems = new ChooserProfileDescriptor[] {
|
||||
createProfileDescriptor(adapter)
|
||||
};
|
||||
@@ -48,8 +50,11 @@ public class ChooserMultiProfilePagerAdapter extends AbstractMultiProfilePagerAd
|
||||
ChooserMultiProfilePagerAdapter(Context context,
|
||||
ChooserActivity.ChooserGridAdapter personalAdapter,
|
||||
ChooserActivity.ChooserGridAdapter workAdapter,
|
||||
@Profile int defaultProfile) {
|
||||
super(context, /* currentPage */ defaultProfile);
|
||||
@Profile int defaultProfile,
|
||||
UserHandle personalProfileUserHandle,
|
||||
UserHandle workProfileUserHandle) {
|
||||
super(context, /* currentPage */ defaultProfile, personalProfileUserHandle,
|
||||
workProfileUserHandle);
|
||||
mItems = new ChooserProfileDescriptor[] {
|
||||
createProfileDescriptor(personalAdapter),
|
||||
createProfileDescriptor(workAdapter)
|
||||
@@ -130,6 +135,17 @@ public class ChooserMultiProfilePagerAdapter extends AbstractMultiProfilePagerAd
|
||||
return getAdapterForIndex(1 - getCurrentPage()).getListAdapter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResolverListAdapter getPersonalListAdapter() {
|
||||
return getAdapterForIndex(PROFILE_PERSONAL).getListAdapter();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ResolverListAdapter getWorkListAdapter() {
|
||||
return getAdapterForIndex(PROFILE_WORK).getListAdapter();
|
||||
}
|
||||
|
||||
@Override
|
||||
ChooserActivity.ChooserGridAdapter getCurrentRootAdapter() {
|
||||
return getAdapterForIndex(getCurrentPage());
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
|
||||
package com.android.internal.app;
|
||||
|
||||
import static android.Manifest.permission.INTERACT_ACROSS_PROFILES;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||
import static android.content.PermissionChecker.PID_UNKNOWN;
|
||||
|
||||
import static com.android.internal.app.AbstractMultiProfilePagerAdapter.PROFILE_PERSONAL;
|
||||
import static com.android.internal.app.AbstractMultiProfilePagerAdapter.PROFILE_WORK;
|
||||
@@ -36,6 +38,7 @@ import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.PermissionChecker;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
@@ -157,7 +160,8 @@ public class ResolverActivity extends Activity implements
|
||||
private static final String TAB_TAG_PERSONAL = "personal";
|
||||
private static final String TAB_TAG_WORK = "work";
|
||||
|
||||
private final PackageMonitor mPackageMonitor = createPackageMonitor();
|
||||
private PackageMonitor mPersonalPackageMonitor;
|
||||
private PackageMonitor mWorkPackageMonitor;
|
||||
|
||||
@VisibleForTesting
|
||||
protected AbstractMultiProfilePagerAdapter mMultiProfilePagerAdapter;
|
||||
@@ -243,11 +247,11 @@ public class ResolverActivity extends Activity implements
|
||||
}
|
||||
}
|
||||
|
||||
protected PackageMonitor createPackageMonitor() {
|
||||
protected PackageMonitor createPackageMonitor(ResolverListAdapter listAdapter) {
|
||||
return new PackageMonitor() {
|
||||
@Override
|
||||
public void onSomePackagesChanged() {
|
||||
mMultiProfilePagerAdapter.getActiveListAdapter().handlePackagesChanged();
|
||||
listAdapter.handlePackagesChanged();
|
||||
updateProfileViewButton();
|
||||
}
|
||||
|
||||
@@ -327,8 +331,6 @@ public class ResolverActivity extends Activity implements
|
||||
|
||||
mPm = getPackageManager();
|
||||
|
||||
mPackageMonitor.register(this, getMainLooper(), false);
|
||||
mRegistered = true;
|
||||
mReferrerPackage = getReferrerPackageName();
|
||||
|
||||
// Add our initial intent as the first item, regardless of what else has already been added.
|
||||
@@ -353,6 +355,18 @@ public class ResolverActivity extends Activity implements
|
||||
return;
|
||||
}
|
||||
|
||||
mPersonalPackageMonitor = createPackageMonitor(
|
||||
mMultiProfilePagerAdapter.getPersonalListAdapter());
|
||||
mPersonalPackageMonitor.register(
|
||||
this, getMainLooper(), getPersonalProfileUserHandle(), false);
|
||||
if (hasWorkProfile()) {
|
||||
mWorkPackageMonitor = createPackageMonitor(
|
||||
mMultiProfilePagerAdapter.getWorkListAdapter());
|
||||
mWorkPackageMonitor.register(this, getMainLooper(), getWorkProfileUserHandle(), false);
|
||||
}
|
||||
|
||||
mRegistered = true;
|
||||
|
||||
final ResolverDrawerLayout rdl = findViewById(R.id.contentPanel);
|
||||
if (rdl != null) {
|
||||
rdl.setOnDismissedListener(new ResolverDrawerLayout.OnDismissedListener() {
|
||||
@@ -419,7 +433,9 @@ public class ResolverActivity extends Activity implements
|
||||
/* userHandle */ UserHandle.of(UserHandle.myUserId()));
|
||||
return new ResolverMultiProfilePagerAdapter(
|
||||
/* context */ this,
|
||||
adapter);
|
||||
adapter,
|
||||
getPersonalProfileUserHandle(),
|
||||
/* workProfileUserHandle= */ null);
|
||||
}
|
||||
|
||||
private ResolverMultiProfilePagerAdapter createResolverMultiProfilePagerAdapterForTwoProfiles(
|
||||
@@ -438,20 +454,23 @@ public class ResolverActivity extends Activity implements
|
||||
== getPersonalProfileUserHandle().getIdentifier()),
|
||||
mUseLayoutForBrowsables,
|
||||
/* userHandle */ getPersonalProfileUserHandle());
|
||||
UserHandle workProfileUserHandle = getWorkProfileUserHandle();
|
||||
ResolverListAdapter workAdapter = createResolverListAdapter(
|
||||
/* context */ this,
|
||||
/* payloadIntents */ mIntents,
|
||||
initialIntents,
|
||||
rList,
|
||||
(filterLastUsed && UserHandle.myUserId()
|
||||
== getWorkProfileUserHandle().getIdentifier()),
|
||||
== workProfileUserHandle.getIdentifier()),
|
||||
mUseLayoutForBrowsables,
|
||||
/* userHandle */ getWorkProfileUserHandle());
|
||||
/* userHandle */ workProfileUserHandle);
|
||||
return new ResolverMultiProfilePagerAdapter(
|
||||
/* context */ this,
|
||||
personalAdapter,
|
||||
workAdapter,
|
||||
/* defaultProfile */ getCurrentProfile());
|
||||
/* defaultProfile */ getCurrentProfile(),
|
||||
getPersonalProfileUserHandle(),
|
||||
getWorkProfileUserHandle());
|
||||
}
|
||||
|
||||
protected @Profile int getCurrentProfile() {
|
||||
@@ -543,9 +562,6 @@ 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,
|
||||
@@ -707,7 +723,16 @@ public class ResolverActivity extends Activity implements
|
||||
protected void onRestart() {
|
||||
super.onRestart();
|
||||
if (!mRegistered) {
|
||||
mPackageMonitor.register(this, getMainLooper(), false);
|
||||
mPersonalPackageMonitor.register(this, getMainLooper(),
|
||||
getPersonalProfileUserHandle(), false);
|
||||
if (hasWorkProfile()) {
|
||||
if (mWorkPackageMonitor == null) {
|
||||
mWorkPackageMonitor = createPackageMonitor(
|
||||
mMultiProfilePagerAdapter.getWorkListAdapter());
|
||||
}
|
||||
mWorkPackageMonitor.register(this, getMainLooper(),
|
||||
getWorkProfileUserHandle(), false);
|
||||
}
|
||||
mRegistered = true;
|
||||
}
|
||||
mMultiProfilePagerAdapter.getActiveListAdapter().handlePackagesChanged();
|
||||
@@ -718,7 +743,10 @@ public class ResolverActivity extends Activity implements
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
if (mRegistered) {
|
||||
mPackageMonitor.unregister();
|
||||
mPersonalPackageMonitor.unregister();
|
||||
if (mWorkPackageMonitor != null) {
|
||||
mWorkPackageMonitor.unregister();
|
||||
}
|
||||
mRegistered = false;
|
||||
}
|
||||
final Intent intent = getIntent();
|
||||
@@ -913,26 +941,21 @@ public class ResolverActivity extends Activity implements
|
||||
}
|
||||
|
||||
@Override // ResolverListCommunicator
|
||||
public void onPostListReady(ResolverListAdapter listAdapter) {
|
||||
if (mMultiProfilePagerAdapter.getCurrentUserHandle().getIdentifier()
|
||||
== UserHandle.myUserId()) {
|
||||
setHeader();
|
||||
public void onPostListReady(ResolverListAdapter listAdapter, boolean doPostProcessing) {
|
||||
if (isAutolaunching() || maybeAutolaunchActivity()) {
|
||||
return;
|
||||
}
|
||||
if (doPostProcessing) {
|
||||
if (mMultiProfilePagerAdapter.getCurrentUserHandle().getIdentifier()
|
||||
== UserHandle.myUserId()) {
|
||||
setHeader();
|
||||
}
|
||||
resetButtonBar();
|
||||
onListRebuilt(listAdapter);
|
||||
}
|
||||
resetButtonBar();
|
||||
onListRebuilt(listAdapter);
|
||||
}
|
||||
|
||||
protected void onListRebuilt(ResolverListAdapter listAdapter) {
|
||||
int count = listAdapter.getUnfilteredCount();
|
||||
if (count == 1 && listAdapter.getOtherProfile() == null) {
|
||||
// Only one target, so we're a candidate to auto-launch!
|
||||
final TargetInfo target = listAdapter.targetInfoForPosition(0, false);
|
||||
if (shouldAutoLaunchSingleChoice(target)) {
|
||||
safelyStartActivity(target);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
final ItemClickListener listener = new ItemClickListener();
|
||||
setupAdapterListView((ListView) mMultiProfilePagerAdapter.getActiveAdapterView(), listener);
|
||||
}
|
||||
@@ -1132,6 +1155,11 @@ public class ResolverActivity extends Activity implements
|
||||
}
|
||||
|
||||
private void safelyStartActivityInternal(TargetInfo cti) {
|
||||
mPersonalPackageMonitor.unregister();
|
||||
if (mWorkPackageMonitor != null) {
|
||||
mWorkPackageMonitor.unregister();
|
||||
}
|
||||
mRegistered = false;
|
||||
// If needed, show that intent is forwarded
|
||||
// from managed profile to owner or other way around.
|
||||
if (mProfileSwitchMessageId != -1) {
|
||||
@@ -1247,7 +1275,11 @@ public class ResolverActivity extends Activity implements
|
||||
throw new IllegalStateException("mMultiProfilePagerAdapter.getCurrentListAdapter() "
|
||||
+ "cannot be null.");
|
||||
}
|
||||
boolean rebuildCompleted = mMultiProfilePagerAdapter.getActiveListAdapter().rebuildList();
|
||||
boolean rebuildCompleted = mMultiProfilePagerAdapter.rebuildActiveTab(true);
|
||||
|
||||
// We partially rebuild the inactive adapter to determine if we should auto launch
|
||||
mMultiProfilePagerAdapter.rebuildInactiveTab(false);
|
||||
|
||||
if (useLayoutWithDefault()) {
|
||||
mLayoutId = R.layout.resolver_list_with_default;
|
||||
} else {
|
||||
@@ -1274,25 +1306,12 @@ public class ResolverActivity extends Activity implements
|
||||
* @return <code>true</code> if the activity is finishing and creation should halt.
|
||||
*/
|
||||
final boolean postRebuildListInternal(boolean rebuildCompleted) {
|
||||
|
||||
int count = mMultiProfilePagerAdapter.getActiveListAdapter().getUnfilteredCount();
|
||||
|
||||
// We only rebuild asynchronously when we have multiple elements to sort. In the case where
|
||||
// we're already done, we can check if we should auto-launch immediately.
|
||||
if (rebuildCompleted) {
|
||||
if (count == 1
|
||||
&& mMultiProfilePagerAdapter.getActiveListAdapter().getOtherProfile() == null) {
|
||||
// Only one target, so we're a candidate to auto-launch!
|
||||
final TargetInfo target = mMultiProfilePagerAdapter.getActiveListAdapter()
|
||||
.targetInfoForPosition(0, false);
|
||||
if (shouldAutoLaunchSingleChoice(target)) {
|
||||
safelyStartActivity(target);
|
||||
mPackageMonitor.unregister();
|
||||
mRegistered = false;
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (rebuildCompleted && maybeAutolaunchActivity()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
setupViewVisibilities();
|
||||
@@ -1304,6 +1323,129 @@ public class ResolverActivity extends Activity implements
|
||||
return false;
|
||||
}
|
||||
|
||||
private int isPermissionGranted(String permission, int uid) {
|
||||
return ActivityManager.checkComponentPermission(permission, uid,
|
||||
/* owningUid= */-1, /* exported= */ true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if a resolved target is autolaunched, otherwise {@code false}
|
||||
*/
|
||||
private boolean maybeAutolaunchActivity() {
|
||||
int numberOfProfiles = mMultiProfilePagerAdapter.getItemCount();
|
||||
if (numberOfProfiles == 1 && maybeAutolaunchIfSingleTarget()) {
|
||||
return true;
|
||||
} else if (numberOfProfiles == 2 && maybeAutolaunchIfCrossProfileSupported()) {
|
||||
// note that autolaunching when we have 2 profiles, 1 resolved target on the active
|
||||
// tab and 0 resolved targets on the inactive tab, is already handled before launching
|
||||
// ResolverActivity
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean maybeAutolaunchIfSingleTarget() {
|
||||
int count = mMultiProfilePagerAdapter.getActiveListAdapter().getUnfilteredCount();
|
||||
if (count != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only one target, so we're a candidate to auto-launch!
|
||||
final TargetInfo target = mMultiProfilePagerAdapter.getActiveListAdapter()
|
||||
.targetInfoForPosition(0, false);
|
||||
if (shouldAutoLaunchSingleChoice(target)) {
|
||||
safelyStartActivity(target);
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* When we have a personal and a work profile, we auto launch in the following scenario:
|
||||
* - There is 1 resolved target on each profile
|
||||
* - That target is the same app on both profiles
|
||||
* - The target app has permission to communicate cross profiles
|
||||
* - The target app has declared it supports cross-profile communication via manifest metadata
|
||||
*/
|
||||
private boolean maybeAutolaunchIfCrossProfileSupported() {
|
||||
int count = mMultiProfilePagerAdapter.getActiveListAdapter().getUnfilteredCount();
|
||||
if (count != 1) {
|
||||
return false;
|
||||
}
|
||||
ResolverListAdapter inactiveListAdapter =
|
||||
mMultiProfilePagerAdapter.getInactiveListAdapter();
|
||||
if (inactiveListAdapter.getUnfilteredCount() != 1) {
|
||||
return false;
|
||||
}
|
||||
TargetInfo activeProfileTarget = mMultiProfilePagerAdapter.getActiveListAdapter()
|
||||
.targetInfoForPosition(0, false);
|
||||
TargetInfo inactiveProfileTarget = inactiveListAdapter.targetInfoForPosition(0, false);
|
||||
if (!Objects.equals(activeProfileTarget.getResolvedComponentName(),
|
||||
inactiveProfileTarget.getResolvedComponentName())) {
|
||||
return false;
|
||||
}
|
||||
if (!shouldAutoLaunchSingleChoice(activeProfileTarget)) {
|
||||
return false;
|
||||
}
|
||||
String packageName = activeProfileTarget.getResolvedComponentName().getPackageName();
|
||||
if (!canAppInteractCrossProfiles(packageName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
safelyStartActivity(activeProfileTarget);
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the package has the necessary permissions to interact across profiles on
|
||||
* behalf of a given user.
|
||||
*
|
||||
* <p>This means meeting the following condition:
|
||||
* <ul>
|
||||
* <li>The app's {@link ApplicationInfo#crossProfile} flag must be true, and at least
|
||||
* one of the following conditions must be fulfilled</li>
|
||||
* <li>{@code Manifest.permission.INTERACT_ACROSS_USERS_FULL} granted.</li>
|
||||
* <li>{@code Manifest.permission.INTERACT_ACROSS_USERS} granted.</li>
|
||||
* <li>{@code Manifest.permission.INTERACT_ACROSS_PROFILES} granted, or the corresponding
|
||||
* AppOps {@code android:interact_across_profiles} is set to "allow".</li>
|
||||
* </ul>
|
||||
*
|
||||
*/
|
||||
private boolean canAppInteractCrossProfiles(String packageName) {
|
||||
ApplicationInfo applicationInfo;
|
||||
try {
|
||||
applicationInfo = getPackageManager().getApplicationInfo(packageName, 0);
|
||||
} catch (NameNotFoundException e) {
|
||||
Log.e(TAG, "Package " + packageName + " does not exist on current user.");
|
||||
return false;
|
||||
}
|
||||
if (!applicationInfo.crossProfile) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int packageUid = applicationInfo.uid;
|
||||
|
||||
if (isPermissionGranted(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
|
||||
packageUid) == PackageManager.PERMISSION_GRANTED) {
|
||||
return true;
|
||||
}
|
||||
if (isPermissionGranted(android.Manifest.permission.INTERACT_ACROSS_USERS, packageUid)
|
||||
== PackageManager.PERMISSION_GRANTED) {
|
||||
return true;
|
||||
}
|
||||
if (PermissionChecker.checkPermissionForPreflight(this, INTERACT_ACROSS_PROFILES,
|
||||
PID_UNKNOWN, packageUid, packageName) == PackageManager.PERMISSION_GRANTED) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isAutolaunching() {
|
||||
return !mRegistered && isFinishing();
|
||||
}
|
||||
|
||||
private void setupProfileTabs() {
|
||||
TabHost tabHost = findViewById(R.id.profile_tabhost);
|
||||
tabHost.setup();
|
||||
@@ -1499,12 +1641,20 @@ public class ResolverActivity extends Activity implements
|
||||
}
|
||||
|
||||
@Override // ResolverListCommunicator
|
||||
public void onHandlePackagesChanged() {
|
||||
ResolverListAdapter activeListAdapter = mMultiProfilePagerAdapter.getActiveListAdapter();
|
||||
activeListAdapter.rebuildList();
|
||||
if (activeListAdapter.getCount() == 0) {
|
||||
// We no longer have any items... just finish the activity.
|
||||
finish();
|
||||
public void onHandlePackagesChanged(ResolverListAdapter listAdapter) {
|
||||
if (listAdapter == mMultiProfilePagerAdapter.getActiveListAdapter()) {
|
||||
boolean listRebuilt = mMultiProfilePagerAdapter.rebuildActiveTab(true);
|
||||
if (listRebuilt) {
|
||||
ResolverListAdapter activeListAdapter =
|
||||
mMultiProfilePagerAdapter.getActiveListAdapter();
|
||||
activeListAdapter.notifyDataSetChanged();
|
||||
if (activeListAdapter.getCount() == 0) {
|
||||
// We no longer have any items... just finish the activity.
|
||||
finish();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mMultiProfilePagerAdapter.clearInactiveProfileCache();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ public class ResolverListAdapter extends BaseAdapter {
|
||||
}
|
||||
|
||||
public void handlePackagesChanged() {
|
||||
mResolverListCommunicator.onHandlePackagesChanged();
|
||||
mResolverListCommunicator.onHandlePackagesChanged(this);
|
||||
}
|
||||
|
||||
public void setPlaceholderCount(int count) {
|
||||
@@ -176,9 +176,14 @@ public class ResolverListAdapter extends BaseAdapter {
|
||||
* Rebuild the list of resolvers. In some cases some parts will need some asynchronous work
|
||||
* to complete.
|
||||
*
|
||||
* The {@code doPostProcessing } parameter is used to specify whether to update the UI and
|
||||
* load additional targets (e.g. direct share) after the list has been rebuilt. This is used
|
||||
* in the case where we want to load the inactive profile's resolved apps to know the
|
||||
* number of targets.
|
||||
*
|
||||
* @return Whether or not the list building is completed.
|
||||
*/
|
||||
protected boolean rebuildList() {
|
||||
protected boolean rebuildList(boolean doPostProcessing) {
|
||||
List<ResolvedComponentInfo> currentResolveList = null;
|
||||
// Clear the value of mOtherProfile from previous call.
|
||||
mOtherProfile = null;
|
||||
@@ -186,6 +191,7 @@ public class ResolverListAdapter extends BaseAdapter {
|
||||
mLastChosenPosition = -1;
|
||||
mAllTargetsAreBrowsers = false;
|
||||
mDisplayList.clear();
|
||||
|
||||
if (mBaseResolveList != null) {
|
||||
currentResolveList = mUnfilteredResolveList = new ArrayList<>();
|
||||
mResolverListController.addResolveListDedupe(currentResolveList,
|
||||
@@ -198,7 +204,7 @@ public class ResolverListAdapter extends BaseAdapter {
|
||||
mResolverListCommunicator.shouldGetActivityMetadata(),
|
||||
mIntents);
|
||||
if (currentResolveList == null) {
|
||||
processSortedList(currentResolveList);
|
||||
processSortedList(currentResolveList, doPostProcessing);
|
||||
return true;
|
||||
}
|
||||
List<ResolvedComponentInfo> originalList =
|
||||
@@ -256,22 +262,22 @@ public class ResolverListAdapter extends BaseAdapter {
|
||||
--placeholderCount;
|
||||
}
|
||||
setPlaceholderCount(placeholderCount);
|
||||
createSortingTask().execute(currentResolveList);
|
||||
postListReadyRunnable();
|
||||
createSortingTask(doPostProcessing).execute(currentResolveList);
|
||||
postListReadyRunnable(doPostProcessing);
|
||||
return false;
|
||||
} else {
|
||||
processSortedList(currentResolveList);
|
||||
processSortedList(currentResolveList, doPostProcessing);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
processSortedList(currentResolveList);
|
||||
processSortedList(currentResolveList, doPostProcessing);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
AsyncTask<List<ResolvedComponentInfo>,
|
||||
Void,
|
||||
List<ResolvedComponentInfo>> createSortingTask() {
|
||||
List<ResolvedComponentInfo>> createSortingTask(boolean doPostProcessing) {
|
||||
return new AsyncTask<List<ResolvedComponentInfo>,
|
||||
Void,
|
||||
List<ResolvedComponentInfo>>() {
|
||||
@@ -283,15 +289,17 @@ public class ResolverListAdapter extends BaseAdapter {
|
||||
}
|
||||
@Override
|
||||
protected void onPostExecute(List<ResolvedComponentInfo> sortedComponents) {
|
||||
processSortedList(sortedComponents);
|
||||
mResolverListCommunicator.updateProfileViewButton();
|
||||
processSortedList(sortedComponents, doPostProcessing);
|
||||
notifyDataSetChanged();
|
||||
if (doPostProcessing) {
|
||||
mResolverListCommunicator.updateProfileViewButton();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
protected void processSortedList(List<ResolvedComponentInfo> sortedComponents) {
|
||||
protected void processSortedList(List<ResolvedComponentInfo> sortedComponents,
|
||||
boolean doPostProcessing) {
|
||||
int n;
|
||||
if (sortedComponents != null && (n = sortedComponents.size()) != 0) {
|
||||
mAllTargetsAreBrowsers = mUseLayoutForBrowsables;
|
||||
@@ -343,20 +351,23 @@ public class ResolverListAdapter extends BaseAdapter {
|
||||
}
|
||||
|
||||
mResolverListCommunicator.sendVoiceChoicesIfNeeded();
|
||||
postListReadyRunnable();
|
||||
postListReadyRunnable(doPostProcessing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Some necessary methods for creating the list are initiated in onCreate and will also
|
||||
* determine the layout known. We therefore can't update the UI inline and post to the
|
||||
* handler thread to update after the current task is finished.
|
||||
* @param doPostProcessing Whether to update the UI and load additional direct share targets
|
||||
* after the list has been rebuilt
|
||||
*/
|
||||
void postListReadyRunnable() {
|
||||
void postListReadyRunnable(boolean doPostProcessing) {
|
||||
if (mPostListReadyRunnable == null) {
|
||||
mPostListReadyRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mResolverListCommunicator.onPostListReady(ResolverListAdapter.this);
|
||||
mResolverListCommunicator.onPostListReady(ResolverListAdapter.this,
|
||||
doPostProcessing);
|
||||
mPostListReadyRunnable = null;
|
||||
}
|
||||
};
|
||||
@@ -590,6 +601,12 @@ public class ResolverListAdapter extends BaseAdapter {
|
||||
return mResolverListController.getUserHandle();
|
||||
}
|
||||
|
||||
protected List<ResolvedComponentInfo> getResolversForUser(UserHandle userHandle) {
|
||||
return mResolverListController.getResolversForIntentAsUser(true,
|
||||
mResolverListCommunicator.shouldGetActivityMetadata(),
|
||||
mIntents, userHandle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Necessary methods to communicate between {@link ResolverListAdapter}
|
||||
* and {@link ResolverActivity}.
|
||||
@@ -600,7 +617,7 @@ public class ResolverListAdapter extends BaseAdapter {
|
||||
|
||||
Intent getReplacementIntent(ActivityInfo activityInfo, Intent defIntent);
|
||||
|
||||
void onPostListReady(ResolverListAdapter listAdapter);
|
||||
void onPostListReady(ResolverListAdapter listAdapter, boolean updateUi);
|
||||
|
||||
void sendVoiceChoicesIfNeeded();
|
||||
|
||||
@@ -612,7 +629,7 @@ public class ResolverListAdapter extends BaseAdapter {
|
||||
|
||||
Intent getTargetIntent();
|
||||
|
||||
void onHandlePackagesChanged();
|
||||
void onHandlePackagesChanged(ResolverListAdapter listAdapter);
|
||||
}
|
||||
|
||||
static class ViewHolder {
|
||||
|
||||
@@ -111,6 +111,15 @@ public class ResolverListController {
|
||||
boolean shouldGetResolvedFilter,
|
||||
boolean shouldGetActivityMetadata,
|
||||
List<Intent> intents) {
|
||||
return getResolversForIntentAsUser(shouldGetResolvedFilter, shouldGetActivityMetadata,
|
||||
intents, mUserHandle);
|
||||
}
|
||||
|
||||
public List<ResolverActivity.ResolvedComponentInfo> getResolversForIntentAsUser(
|
||||
boolean shouldGetResolvedFilter,
|
||||
boolean shouldGetActivityMetadata,
|
||||
List<Intent> intents,
|
||||
UserHandle userHandle) {
|
||||
List<ResolverActivity.ResolvedComponentInfo> resolvedComponents = null;
|
||||
for (int i = 0, N = intents.size(); i < N; i++) {
|
||||
final Intent intent = intents.get(i);
|
||||
@@ -122,7 +131,7 @@ public class ResolverListController {
|
||||
flags |= PackageManager.MATCH_INSTANT;
|
||||
}
|
||||
final List<ResolveInfo> infos = mpm.queryIntentActivitiesAsUser(intent, flags,
|
||||
mUserHandle);
|
||||
userHandle);
|
||||
if (infos != null) {
|
||||
if (resolvedComponents == null) {
|
||||
resolvedComponents = new ArrayList<>();
|
||||
|
||||
@@ -36,8 +36,10 @@ public class ResolverMultiProfilePagerAdapter extends AbstractMultiProfilePagerA
|
||||
private final ResolverProfileDescriptor[] mItems;
|
||||
|
||||
ResolverMultiProfilePagerAdapter(Context context,
|
||||
ResolverListAdapter adapter) {
|
||||
super(context, /* currentPage */ 0);
|
||||
ResolverListAdapter adapter,
|
||||
UserHandle personalProfileUserHandle,
|
||||
UserHandle workProfileUserHandle) {
|
||||
super(context, /* currentPage */ 0, personalProfileUserHandle, workProfileUserHandle);
|
||||
mItems = new ResolverProfileDescriptor[] {
|
||||
createProfileDescriptor(adapter)
|
||||
};
|
||||
@@ -46,8 +48,11 @@ public class ResolverMultiProfilePagerAdapter extends AbstractMultiProfilePagerA
|
||||
ResolverMultiProfilePagerAdapter(Context context,
|
||||
ResolverListAdapter personalAdapter,
|
||||
ResolverListAdapter workAdapter,
|
||||
@Profile int defaultProfile) {
|
||||
super(context, /* currentPage */ defaultProfile);
|
||||
@Profile int defaultProfile,
|
||||
UserHandle personalProfileUserHandle,
|
||||
UserHandle workProfileUserHandle) {
|
||||
super(context, /* currentPage */ defaultProfile, personalProfileUserHandle,
|
||||
workProfileUserHandle);
|
||||
mItems = new ResolverProfileDescriptor[] {
|
||||
createProfileDescriptor(personalAdapter),
|
||||
createProfileDescriptor(workAdapter)
|
||||
@@ -115,6 +120,17 @@ public class ResolverMultiProfilePagerAdapter extends AbstractMultiProfilePagerA
|
||||
return getAdapterForIndex(1 - getCurrentPage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResolverListAdapter getPersonalListAdapter() {
|
||||
return getAdapterForIndex(PROFILE_PERSONAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ResolverListAdapter getWorkListAdapter() {
|
||||
return getAdapterForIndex(PROFILE_WORK);
|
||||
}
|
||||
|
||||
@Override
|
||||
ResolverListAdapter getCurrentRootAdapter() {
|
||||
return getActiveListAdapter();
|
||||
|
||||
@@ -27,12 +27,14 @@ import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
||||
|
||||
import static com.android.internal.app.MatcherUtils.first;
|
||||
import static com.android.internal.app.ResolverDataProvider.createPackageManagerMockedInfo;
|
||||
import static com.android.internal.app.ResolverDataProvider.createResolvedComponentInfoWithOtherId;
|
||||
import static com.android.internal.app.ResolverWrapperActivity.sOverrides;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.allOf;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Intent;
|
||||
@@ -465,14 +467,33 @@ public class ResolverActivityTest {
|
||||
// enable the work tab feature flag
|
||||
ResolverActivity.ENABLE_TABBED_VIEW = true;
|
||||
List<ResolvedComponentInfo> personalResolvedComponentInfos =
|
||||
createResolvedComponentsForTest(3);
|
||||
createResolvedComponentsForTestWithOtherProfile(3);
|
||||
List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
|
||||
when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
|
||||
when(sOverrides.resolverListController.getResolversForIntentAsUser(
|
||||
Mockito.anyBoolean(),
|
||||
Mockito.isA(List.class))).thenReturn(personalResolvedComponentInfos);
|
||||
Mockito.anyBoolean(),
|
||||
Mockito.isA(List.class),
|
||||
eq(UserHandle.SYSTEM))).thenReturn(new ArrayList<>(personalResolvedComponentInfos));
|
||||
when(sOverrides.resolverListController.getResolversForIntentAsUser(
|
||||
Mockito.anyBoolean(),
|
||||
Mockito.anyBoolean(),
|
||||
Mockito.isA(List.class),
|
||||
eq(sOverrides.workProfileUserHandle))).thenReturn(new ArrayList<>(workResolvedComponentInfos));
|
||||
when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(),
|
||||
Mockito.anyBoolean(),
|
||||
Mockito.isA(List.class),
|
||||
eq(sOverrides.workProfileUserHandle))).thenReturn(new ArrayList<>(workResolvedComponentInfos));
|
||||
when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(),
|
||||
Mockito.anyBoolean(),
|
||||
Mockito.isA(List.class))).thenReturn(workResolvedComponentInfos);
|
||||
Mockito.isA(List.class))).thenReturn(new ArrayList<>(workResolvedComponentInfos));
|
||||
when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
|
||||
Mockito.anyBoolean(),
|
||||
Mockito.isA(List.class))).thenReturn(new ArrayList<>(personalResolvedComponentInfos));
|
||||
when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(),
|
||||
Mockito.anyBoolean(),
|
||||
Mockito.isA(List.class),
|
||||
eq(UserHandle.SYSTEM))).thenReturn(new ArrayList<>(personalResolvedComponentInfos));
|
||||
|
||||
Intent sendIntent = createSendImageIntent();
|
||||
markWorkProfileUserAvailable();
|
||||
|
||||
@@ -502,9 +523,9 @@ public class ResolverActivityTest {
|
||||
|
||||
final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
|
||||
waitForIdle();
|
||||
|
||||
onView(withText(R.string.resolver_work_tab))
|
||||
.perform(click());
|
||||
|
||||
waitForIdle();
|
||||
assertThat(activity.getWorkListAdapter().getCount(), is(4));
|
||||
}
|
||||
@@ -553,10 +574,35 @@ public class ResolverActivityTest {
|
||||
// enable the work tab feature flag
|
||||
ResolverActivity.ENABLE_TABBED_VIEW = true;
|
||||
markWorkProfileUserAvailable();
|
||||
List<ResolvedComponentInfo> personalResolvedComponentInfos =
|
||||
createResolvedComponentsForTestWithOtherProfile(1);
|
||||
List<ResolvedComponentInfo> workResolvedComponentInfos = createResolvedComponentsForTest(4);
|
||||
|
||||
when(sOverrides.resolverListController.getResolversForIntentAsUser(
|
||||
Mockito.anyBoolean(),
|
||||
Mockito.anyBoolean(),
|
||||
Mockito.isA(List.class),
|
||||
eq(UserHandle.SYSTEM))).thenReturn(new ArrayList<>(personalResolvedComponentInfos));
|
||||
when(sOverrides.resolverListController.getResolversForIntentAsUser(
|
||||
Mockito.anyBoolean(),
|
||||
Mockito.anyBoolean(),
|
||||
Mockito.isA(List.class),
|
||||
eq(sOverrides.workProfileUserHandle))).thenReturn(new ArrayList<>(workResolvedComponentInfos));
|
||||
when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(),
|
||||
Mockito.anyBoolean(),
|
||||
Mockito.isA(List.class),
|
||||
eq(sOverrides.workProfileUserHandle))).thenReturn(new ArrayList<>(workResolvedComponentInfos));
|
||||
when(sOverrides.workResolverListController.getResolversForIntent(Mockito.anyBoolean(),
|
||||
Mockito.anyBoolean(),
|
||||
Mockito.isA(List.class))).thenReturn(workResolvedComponentInfos);
|
||||
Mockito.isA(List.class))).thenReturn(new ArrayList<>(workResolvedComponentInfos));
|
||||
when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
|
||||
Mockito.anyBoolean(),
|
||||
Mockito.isA(List.class))).thenReturn(new ArrayList<>(personalResolvedComponentInfos));
|
||||
when(sOverrides.workResolverListController.getResolversForIntentAsUser(Mockito.anyBoolean(),
|
||||
Mockito.anyBoolean(),
|
||||
Mockito.isA(List.class),
|
||||
eq(UserHandle.SYSTEM))).thenReturn(new ArrayList<>(personalResolvedComponentInfos));
|
||||
|
||||
Intent sendIntent = createSendImageIntent();
|
||||
|
||||
final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
|
||||
|
||||
Reference in New Issue
Block a user