From 81e474d7a73516faa1e45a6279020471aa453232 Mon Sep 17 00:00:00 2001 From: Matt Casey Date: Wed, 26 Jan 2022 17:13:46 -0500 Subject: [PATCH] Add 'miniresolver' UI for cross-profile single app resolution. When the current profile only has web browsers and the other profile has a single non-browser app to handle the given intent, simplify the resolver UI to present the user with a yes/no question about how to handle. Canonical example of this is "clicking a youtube link in your work profile". Bug: 175433480 Test: atest ResolverActivityTest Change-Id: I213313ca87a8d1db5e586fe074f953060a91fc19 --- .../internal/app/ResolverActivity.java | 79 ++++++++++++- core/res/res/layout/miniresolver.xml | 111 ++++++++++++++++++ core/res/res/values/strings.xml | 4 +- core/res/res/values/symbols.xml | 8 ++ .../internal/app/ResolverActivityTest.java | 19 +++ 5 files changed, 217 insertions(+), 4 deletions(-) create mode 100644 core/res/res/layout/miniresolver.xml diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index 347153c7e53ea..cdb69e546b8f8 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -1011,7 +1011,9 @@ public class ResolverActivity extends Activity implements protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); ViewPager viewPager = findViewById(R.id.profile_pager); - outState.putInt(LAST_SHOWN_TAB_KEY, viewPager.getCurrentItem()); + if (viewPager != null) { + outState.putInt(LAST_SHOWN_TAB_KEY, viewPager.getCurrentItem()); + } } @Override @@ -1019,7 +1021,9 @@ public class ResolverActivity extends Activity implements super.onRestoreInstanceState(savedInstanceState); resetButtonBar(); ViewPager viewPager = findViewById(R.id.profile_pager); - viewPager.setCurrentItem(savedInstanceState.getInt(LAST_SHOWN_TAB_KEY)); + if (viewPager != null) { + viewPager.setCurrentItem(savedInstanceState.getInt(LAST_SHOWN_TAB_KEY)); + } mMultiProfilePagerAdapter.clearInactiveProfileCache(); } @@ -1568,6 +1572,11 @@ public class ResolverActivity extends Activity implements rebuildCompleted = rebuildCompleted && rebuildInactiveCompleted; } + if (shouldUseMiniResolver()) { + configureMiniResolverContent(); + return false; + } + if (useLayoutWithDefault()) { mLayoutId = R.layout.resolver_list_with_default; } else { @@ -1578,6 +1587,72 @@ public class ResolverActivity extends Activity implements return postRebuildList(rebuildCompleted); } + private void configureMiniResolverContent() { + mLayoutId = R.layout.miniresolver; + setContentView(mLayoutId); + + DisplayResolveInfo sameProfileResolveInfo = + mMultiProfilePagerAdapter.getActiveListAdapter().mDisplayList.get(0); + boolean inWorkProfile = getCurrentProfile() == PROFILE_WORK; + + DisplayResolveInfo otherProfileResolveInfo = + mMultiProfilePagerAdapter.getInactiveListAdapter().mDisplayList.get(0); + ImageView icon = findViewById(R.id.icon); + // TODO: Set icon drawable to app icon. + + ((TextView) findViewById(R.id.open_cross_profile)).setText( + getResources().getString( + inWorkProfile ? R.string.miniresolver_open_in_personal + : R.string.miniresolver_open_in_work, + otherProfileResolveInfo.getDisplayLabel())); + ((Button) findViewById(R.id.use_same_profile_browser)).setText( + inWorkProfile ? R.string.miniresolver_use_work_browser + : R.string.miniresolver_use_personal_browser); + + findViewById(R.id.use_same_profile_browser).setOnClickListener( + v -> safelyStartActivity(sameProfileResolveInfo)); + + findViewById(R.id.button_open).setOnClickListener(v -> { + Intent intent = otherProfileResolveInfo.getResolvedIntent(); + if (intent != null) { + prepareIntentForCrossProfileLaunch(intent); + } + safelyStartActivityInternal(otherProfileResolveInfo, + mMultiProfilePagerAdapter.getInactiveListAdapter().mResolverListController + .getUserHandle()); + }); + } + + private boolean shouldUseMiniResolver() { + if (mMultiProfilePagerAdapter.getActiveListAdapter() == null + || mMultiProfilePagerAdapter.getInactiveListAdapter() == null) { + return false; + } + List sameProfileList = + mMultiProfilePagerAdapter.getActiveListAdapter().mDisplayList; + List otherProfileList = + mMultiProfilePagerAdapter.getInactiveListAdapter().mDisplayList; + + if (otherProfileList.size() != 1) { + Log.d(TAG, "Found " + otherProfileList.size() + " resolvers in the other profile"); + return false; + } + + if (otherProfileList.get(0).getResolveInfo().handleAllWebDataURI) { + Log.d(TAG, "Other profile is a web browser"); + return false; + } + + for (DisplayResolveInfo info : sameProfileList) { + if (!info.getResolveInfo().handleAllWebDataURI) { + Log.d(TAG, "Non-browser found in this profile"); + return false; + } + } + + return true; + } + /** * Finishing procedures to be performed after the list has been rebuilt. *

Subclasses must call postRebuildListInternal at the end of postRebuildList. diff --git a/core/res/res/layout/miniresolver.xml b/core/res/res/layout/miniresolver.xml new file mode 100644 index 0000000000000..44ed6f2a06765 --- /dev/null +++ b/core/res/res/layout/miniresolver.xml @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + +