Merge "Add 'miniresolver' UI for cross-profile single app resolution."
This commit is contained in:
@@ -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<DisplayResolveInfo> sameProfileList =
|
||||
mMultiProfilePagerAdapter.getActiveListAdapter().mDisplayList;
|
||||
List<DisplayResolveInfo> 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.
|
||||
* </p>Subclasses must call postRebuildListInternal at the end of postRebuildList.
|
||||
|
||||
111
core/res/res/layout/miniresolver.xml
Normal file
111
core/res/res/layout/miniresolver.xml
Normal file
@@ -0,0 +1,111 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2022 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.
|
||||
-->
|
||||
<com.android.internal.widget.ResolverDrawerLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:maxWidth="@dimen/resolver_max_width"
|
||||
android:maxCollapsedHeight="@dimen/resolver_max_collapsed_height"
|
||||
android:maxCollapsedHeightSmall="56dp"
|
||||
android:id="@id/contentPanel">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/title_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alwaysShow="true"
|
||||
android:elevation="@dimen/resolver_elevation"
|
||||
android:paddingTop="@dimen/resolver_small_margin"
|
||||
android:paddingStart="@dimen/resolver_edge_margin"
|
||||
android:paddingEnd="@dimen/resolver_edge_margin"
|
||||
android:paddingBottom="@dimen/resolver_title_padding_bottom"
|
||||
android:background="@drawable/bottomsheet_background">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/open_cross_profile"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/icon"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
/>
|
||||
</RelativeLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/button_bar_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alwaysShow="true"
|
||||
android:orientation="vertical"
|
||||
android:background="?attr/colorBackground"
|
||||
android:layout_ignoreOffset="true">
|
||||
<View
|
||||
android:id="@+id/resolver_button_bar_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?attr/colorBackground"
|
||||
android:foreground="?attr/dividerVertical" />
|
||||
<RelativeLayout
|
||||
style="?attr/buttonBarStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_ignoreOffset="true"
|
||||
android:layout_hasNestedScrollIndicator="true"
|
||||
android:gravity="end|center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:layoutDirection="locale"
|
||||
android:measureWithLargestChild="true"
|
||||
android:paddingTop="@dimen/resolver_button_bar_spacing"
|
||||
android:paddingBottom="@dimen/resolver_button_bar_spacing"
|
||||
android:paddingStart="@dimen/resolver_edge_margin"
|
||||
android:paddingEnd="@dimen/resolver_small_margin"
|
||||
android:elevation="@dimen/resolver_elevation">
|
||||
|
||||
<Button
|
||||
android:id="@+id/use_same_profile_browser"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentStart="true"
|
||||
android:maxLines="2"
|
||||
style="@android:style/Widget.DeviceDefault.Button.Borderless"
|
||||
android:fontFamily="@android:string/config_headlineFontFamilyMedium"
|
||||
android:textAllCaps="false"
|
||||
android:text="@string/activity_resolver_use_once"
|
||||
/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_open"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:maxLines="2"
|
||||
style="@android:style/Widget.DeviceDefault.Button.Colored"
|
||||
android:fontFamily="@android:string/config_headlineFontFamilyMedium"
|
||||
android:textAllCaps="false"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/whichViewApplicationLabel"
|
||||
/>
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
</com.android.internal.widget.ResolverDrawerLayout>
|
||||
@@ -5936,9 +5936,9 @@
|
||||
<string name="resolver_no_personal_apps_available">No personal apps</string>
|
||||
|
||||
<!-- Dialog title. User must choose between opening content in a cross-profile app or same-profile browser. [CHAR LIMIT=NONE] -->
|
||||
<string name="miniresolver_open_in_personal">Open in <xliff:g id="app" example="YouTube">%s</xliff:g> in personal profile?</string>
|
||||
<string name="miniresolver_open_in_personal">Open <xliff:g id="app" example="YouTube">%s</xliff:g> in your personal profile?</string>
|
||||
<!-- Dialog title. User must choose between opening content in a cross-profile app or same-profile browser. [CHAR LIMIT=NONE] -->
|
||||
<string name="miniresolver_open_in_work">Open in <xliff:g id="app" example="YouTube">%s</xliff:g> in work profile?</string>
|
||||
<string name="miniresolver_open_in_work">Open <xliff:g id="app" example="YouTube">%s</xliff:g> in your work profile?</string>
|
||||
<!-- Button option. Open the link in the personal browser. [CHAR LIMIT=NONE] -->
|
||||
<string name="miniresolver_use_personal_browser">Use personal browser</string>
|
||||
<!-- Button option. Open the link in the work browser. [CHAR LIMIT=NONE] -->
|
||||
|
||||
@@ -1599,6 +1599,13 @@
|
||||
<java-symbol type="layout" name="resolver_list_per_profile" />
|
||||
<java-symbol type="layout" name="chooser_list_per_profile" />
|
||||
<java-symbol type="layout" name="resolver_empty_states" />
|
||||
<java-symbol type="id" name="open_cross_profile" />
|
||||
<java-symbol type="string" name="miniresolver_open_in_personal" />
|
||||
<java-symbol type="string" name="miniresolver_open_in_work" />
|
||||
<java-symbol type="string" name="miniresolver_use_personal_browser" />
|
||||
<java-symbol type="string" name="miniresolver_use_work_browser" />
|
||||
<java-symbol type="id" name="button_open" />
|
||||
<java-symbol type="id" name="use_same_profile_browser" />
|
||||
|
||||
<java-symbol type="anim" name="slide_in_child_bottom" />
|
||||
<java-symbol type="anim" name="slide_in_right" />
|
||||
@@ -2715,6 +2722,7 @@
|
||||
<java-symbol type="bool" name="config_allow_ussd_over_ims" />
|
||||
<java-symbol type="attr" name="touchscreenBlocksFocus" />
|
||||
<java-symbol type="layout" name="resolver_list_with_default" />
|
||||
<java-symbol type="layout" name="miniresolver" />
|
||||
<java-symbol type="string" name="activity_resolver_use_always" />
|
||||
<java-symbol type="string" name="whichApplicationNamed" />
|
||||
<java-symbol type="string" name="whichApplicationLabel" />
|
||||
|
||||
@@ -730,6 +730,25 @@ public class ResolverActivityTest {
|
||||
.check(matches(isDisplayed()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMiniResolver() {
|
||||
ResolverActivity.ENABLE_TABBED_VIEW = true;
|
||||
markWorkProfileUserAvailable();
|
||||
List<ResolvedComponentInfo> personalResolvedComponentInfos =
|
||||
createResolvedComponentsForTest(1);
|
||||
List<ResolvedComponentInfo> workResolvedComponentInfos =
|
||||
createResolvedComponentsForTest(1);
|
||||
// Personal profile only has a browser
|
||||
personalResolvedComponentInfos.get(0).getResolveInfoAt(0).handleAllWebDataURI = true;
|
||||
setupResolverControllers(personalResolvedComponentInfos, workResolvedComponentInfos);
|
||||
Intent sendIntent = createSendImageIntent();
|
||||
sendIntent.setType("TestType");
|
||||
|
||||
mActivityRule.launchActivity(sendIntent);
|
||||
waitForIdle();
|
||||
onView(withId(R.id.open_cross_profile)).check(matches(isDisplayed()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWorkTab_noAppsAvailable_workOff_noAppsAvailableEmptyStateShown() {
|
||||
// enable the work tab feature flag
|
||||
|
||||
Reference in New Issue
Block a user