diff --git a/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java b/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java index ab8c19ea88619..78e85180f3d24 100644 --- a/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java +++ b/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java @@ -15,15 +15,25 @@ */ package com.android.internal.app; +import android.annotation.DrawableRes; import android.annotation.IntDef; import android.annotation.Nullable; +import android.annotation.StringRes; +import android.app.AppGlobals; +import android.content.ContentResolver; import android.content.Context; +import android.content.Intent; +import android.content.pm.IPackageManager; import android.content.pm.ResolveInfo; import android.os.UserHandle; import android.os.UserManager; import android.view.View; import android.view.ViewGroup; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.TextView; +import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.widget.PagerAdapter; import com.android.internal.widget.ViewPager; @@ -213,26 +223,115 @@ public abstract class AbstractMultiProfilePagerAdapter extends PagerAdapter { abstract @Nullable ViewGroup getInactiveAdapterView(); - boolean rebuildActiveTab(boolean post) { - return rebuildTab(getActiveListAdapter(), post); + /** + * Rebuilds the tab that is currently visible to the user. + *

Returns {@code true} if rebuild has completed. + */ + boolean rebuildActiveTab(boolean doPostProcessing) { + return rebuildTab(getActiveListAdapter(), doPostProcessing); } - boolean rebuildInactiveTab(boolean post) { + /** + * Rebuilds the tab that is not currently visible to the user, if such one exists. + *

Returns {@code true} if rebuild has completed. + */ + boolean rebuildInactiveTab(boolean doPostProcessing) { if (getItemCount() == 1) { return false; } - return rebuildTab(getInactiveListAdapter(), post); + return rebuildTab(getInactiveListAdapter(), doPostProcessing); + } + + private int userHandleToPageIndex(UserHandle userHandle) { + if (userHandle == getPersonalListAdapter().mResolverListController.getUserHandle()) { + return PROFILE_PERSONAL; + } else { + return PROFILE_WORK; + } } 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 + UserManager userManager = mContext.getSystemService(UserManager.class); + if (listUserHandle == mWorkProfileUserHandle + && userManager.isQuietModeEnabled(mWorkProfileUserHandle)) { + showEmptyState(activeListAdapter, + R.drawable.ic_work_apps_off, + R.string.resolver_turn_on_work_apps, + R.string.resolver_turn_on_work_apps_explanation, + (View.OnClickListener) v -> + userManager.requestQuietModeEnabled(false, mWorkProfileUserHandle)); return false; - } else { - return activeListAdapter.rebuildList(doPostProcessing); } + if (UserHandle.myUserId() != listUserHandle.getIdentifier()) { + if (!hasCrossProfileIntents(activeListAdapter.getIntents(), + UserHandle.myUserId(), listUserHandle.getIdentifier())) { + if (listUserHandle == mPersonalProfileUserHandle) { + showEmptyState(activeListAdapter, + R.drawable.ic_sharing_disabled, + R.string.resolver_cant_share_with_personal_apps, + R.string.resolver_cant_share_cross_profile_explanation); + } else { + showEmptyState(activeListAdapter, + R.drawable.ic_sharing_disabled, + R.string.resolver_cant_share_with_work_apps, + R.string.resolver_cant_share_cross_profile_explanation); + } + return false; + } + } + return activeListAdapter.rebuildList(doPostProcessing); + } + + void showEmptyState(ResolverListAdapter listAdapter) { + UserHandle listUserHandle = listAdapter.getUserHandle(); + if (UserHandle.myUserId() == listUserHandle.getIdentifier() + || !hasAppsInOtherProfile(listAdapter)) { + showEmptyState(listAdapter, + R.drawable.ic_no_apps, + R.string.resolver_no_apps_available, + R.string.resolver_no_apps_available_explanation); + } + } + + private void showEmptyState(ResolverListAdapter activeListAdapter, + @DrawableRes int iconRes, @StringRes int titleRes, @StringRes int subtitleRes) { + showEmptyState(activeListAdapter, iconRes, titleRes, subtitleRes, /* buttonOnClick */ null); + } + + private void showEmptyState(ResolverListAdapter activeListAdapter, + @DrawableRes int iconRes, @StringRes int titleRes, @StringRes int subtitleRes, + View.OnClickListener buttonOnClick) { + ProfileDescriptor descriptor = getItem( + userHandleToPageIndex(activeListAdapter.getUserHandle())); + descriptor.rootView.findViewById(R.id.resolver_list).setVisibility(View.GONE); + View emptyStateView = descriptor.rootView.findViewById(R.id.resolver_empty_state); + emptyStateView.setVisibility(View.VISIBLE); + + ImageView icon = emptyStateView.findViewById(R.id.resolver_empty_state_icon); + icon.setImageResource(iconRes); + + TextView title = emptyStateView.findViewById(R.id.resolver_empty_state_title); + title.setText(titleRes); + + TextView subtitle = emptyStateView.findViewById(R.id.resolver_empty_state_subtitle); + subtitle.setText(subtitleRes); + + Button button = emptyStateView.findViewById(R.id.resolver_empty_state_button); + button.setVisibility(buttonOnClick != null ? View.VISIBLE : View.GONE); + button.setOnClickListener(buttonOnClick); + } + + private boolean hasCrossProfileIntents(List intents, int source, int target) { + IPackageManager packageManager = AppGlobals.getPackageManager(); + ContentResolver contentResolver = mContext.getContentResolver(); + for (Intent intent : intents) { + if (IntentForwarderActivity.canForward(intent, source, target, packageManager, + contentResolver) != null) { + return true; + } + } + return false; } private boolean hasAppsInOtherProfile(ResolverListAdapter adapter) { diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index 65cad834d5be0..07ca79acc293b 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -373,7 +373,11 @@ public class ChooserActivity extends ResolverActivity implements Log.i(TAG, "Hiding image preview area. Timed out waiting for preview to load" + " within " + mImageLoadTimeoutMillis + "ms."); collapseParentView(); - hideContentPreview(); + if (hasWorkProfile() && ENABLE_TABBED_VIEW) { + hideStickyContentPreview(); + } else if (mChooserMultiProfilePagerAdapter.getCurrentRootAdapter() != null) { + mChooserMultiProfilePagerAdapter.getCurrentRootAdapter().hideContentPreview(); + } mHideParentOnFail = false; } } @@ -829,7 +833,12 @@ public class ChooserActivity extends ResolverActivity implements @Override protected boolean postRebuildList(boolean rebuildCompleted) { - updateContentPreview(); + updateStickyContentPreview(); + if (shouldShowStickyContentPreview() + || mChooserMultiProfilePagerAdapter + .getCurrentRootAdapter().getContentPreviewRowCount() != 0) { + logActionShareWithPreview(); + } return postRebuildListInternal(rebuildCompleted); } @@ -978,6 +987,8 @@ public class ChooserActivity extends ResolverActivity implements updateLayoutWidth(R.id.content_preview_text_layout, width, parent); updateLayoutWidth(R.id.content_preview_title_layout, width, parent); updateLayoutWidth(R.id.content_preview_file_layout, width, parent); + findViewById(R.id.content_preview_container) + .setVisibility(shouldShowStickyContentPreview() ? View.VISIBLE : View.GONE); } private void updateLayoutWidth(int layoutResourceId, int width, View parent) { @@ -2413,14 +2424,14 @@ public class ChooserActivity extends ResolverActivity implements // still zero? then use a default height and leave, which // can happen when there are no targets to show - if (rowsToShow == 0 && !shouldShowContentPreview()) { + if (rowsToShow == 0 && !shouldShowStickyContentPreview()) { offset += getResources().getDimensionPixelSize( R.dimen.chooser_max_collapsed_height); mResolverDrawerLayout.setCollapsibleHeightReserved(offset); return; } - if (shouldShowContentPreview()) { + if (shouldShowStickyContentPreview()) { offset += findViewById(R.id.content_preview_container).getHeight(); } @@ -2552,7 +2563,7 @@ public class ChooserActivity extends ResolverActivity implements } private void setupScrollListener() { - if (mResolverDrawerLayout == null) { + if (mResolverDrawerLayout == null || (hasWorkProfile() && ENABLE_TABBED_VIEW)) { return; } final View chooserHeader = mResolverDrawerLayout.findViewById(R.id.chooser_header); @@ -2597,28 +2608,36 @@ public class ChooserActivity extends ResolverActivity implements return false; } - private boolean shouldShowContentPreview() { - return mMultiProfilePagerAdapter.getActiveListAdapter().getCount() > 0 - && isSendAction(getTargetIntent()); + /** + * The sticky content preview is shown only when we have a tabbed view. It's shown above + * the tabs so it is not part of the scrollable list. If we are not in tabbed view, + * we instead show the content preview as a regular list item. + */ + private boolean shouldShowStickyContentPreview() { + return hasWorkProfile() + && ENABLE_TABBED_VIEW + && mMultiProfilePagerAdapter.getListAdapterForUserHandle( + UserHandle.of(UserHandle.myUserId())).getCount() > 0 + && isSendAction(getTargetIntent()) + && getResources().getBoolean(R.bool.sharesheet_show_content_preview); } - private void updateContentPreview() { - if (shouldShowContentPreview()) { - showContentPreview(); + private void updateStickyContentPreview() { + if (shouldShowStickyContentPreview()) { + showStickyContentPreview(); } else { - hideContentPreview(); + hideStickyContentPreview(); } } - private void showContentPreview() { + private void showStickyContentPreview() { ViewGroup contentPreviewContainer = findViewById(R.id.content_preview_container); contentPreviewContainer.setVisibility(View.VISIBLE); ViewGroup contentPreviewView = createContentPreviewView(contentPreviewContainer); contentPreviewContainer.addView(contentPreviewView); - logActionShareWithPreview(); } - private void hideContentPreview() { + private void hideStickyContentPreview() { ViewGroup contentPreviewContainer = findViewById(R.id.content_preview_container); contentPreviewContainer.removeAllViews(); contentPreviewContainer.setVisibility(View.GONE); @@ -2634,6 +2653,7 @@ public class ChooserActivity extends ResolverActivity implements /** * Used to bind types of individual item including * {@link ChooserGridAdapter#VIEW_TYPE_NORMAL}, + * {@link ChooserGridAdapter#VIEW_TYPE_CONTENT_PREVIEW}, * {@link ChooserGridAdapter#VIEW_TYPE_PROFILE}, * and {@link ChooserGridAdapter#VIEW_TYPE_AZ_LABEL}. */ @@ -2695,16 +2715,18 @@ public class ChooserActivity extends ResolverActivity implements private int mChooserTargetWidth = 0; private boolean mShowAzLabelIfPoss; + private boolean mHideContentPreview = false; private boolean mLayoutRequested = false; private int mFooterHeight = 0; private static final int VIEW_TYPE_DIRECT_SHARE = 0; private static final int VIEW_TYPE_NORMAL = 1; - private static final int VIEW_TYPE_PROFILE = 2; - private static final int VIEW_TYPE_AZ_LABEL = 3; - private static final int VIEW_TYPE_CALLER_AND_RANK = 4; - private static final int VIEW_TYPE_FOOTER = 5; + private static final int VIEW_TYPE_CONTENT_PREVIEW = 2; + private static final int VIEW_TYPE_PROFILE = 3; + private static final int VIEW_TYPE_AZ_LABEL = 4; + private static final int VIEW_TYPE_CALLER_AND_RANK = 5; + private static final int VIEW_TYPE_FOOTER = 6; private static final int MAX_TARGETS_PER_ROW_PORTRAIT = 4; private static final int MAX_TARGETS_PER_ROW_LANDSCAPE = 8; @@ -2765,6 +2787,17 @@ public class ChooserActivity extends ResolverActivity implements return maxTargets; } + /** + * Hides the list item content preview. + *

Not to be confused with the sticky content preview which is above the + * personal and work tabs. + */ + public void hideContentPreview() { + mHideContentPreview = true; + mLayoutRequested = true; + notifyDataSetChanged(); + } + public boolean consumeLayoutRequest() { boolean oldValue = mLayoutRequested; mLayoutRequested = false; @@ -2773,7 +2806,8 @@ public class ChooserActivity extends ResolverActivity implements public int getRowCount() { return (int) ( - getProfileRowCount() + getContentPreviewRowCount() + + getProfileRowCount() + getServiceTargetRowCount() + getCallerAndRankedTargetRowCount() + getAzLabelRowCount() @@ -2783,7 +2817,33 @@ public class ChooserActivity extends ResolverActivity implements ); } + /** + * Returns either {@code 0} or {@code 1} depending on whether we want to show the list item + * content preview. Not to be confused with the sticky content preview which is above the + * personal and work tabs. + */ + public int getContentPreviewRowCount() { + // For the tabbed case we show the sticky content preview above the tabs, + // please refer to shouldShowStickyContentPreview + if (hasWorkProfile() && ENABLE_TABBED_VIEW) { + return 0; + } + if (!isSendAction(getTargetIntent())) { + return 0; + } + + if (mHideContentPreview || mChooserListAdapter == null + || mChooserListAdapter.getCount() == 0) { + return 0; + } + + return 1; + } + public int getProfileRowCount() { + if (hasWorkProfile() && ENABLE_TABBED_VIEW) { + return 0; + } return mChooserListAdapter.getOtherProfile() == null ? 0 : 1; } @@ -2815,7 +2875,8 @@ public class ChooserActivity extends ResolverActivity implements @Override public int getItemCount() { return (int) ( - getProfileRowCount() + getContentPreviewRowCount() + + getProfileRowCount() + getServiceTargetRowCount() + getCallerAndRankedTargetRowCount() + getAzLabelRowCount() @@ -2827,6 +2888,8 @@ public class ChooserActivity extends ResolverActivity implements @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { switch (viewType) { + case VIEW_TYPE_CONTENT_PREVIEW: + return new ItemViewHolder(createContentPreviewView(parent), false); case VIEW_TYPE_PROFILE: return new ItemViewHolder(createProfileView(parent), false); case VIEW_TYPE_AZ_LABEL: @@ -2866,7 +2929,10 @@ public class ChooserActivity extends ResolverActivity implements public int getItemViewType(int position) { int count; - int countSum = (count = getProfileRowCount()); + int countSum = (count = getContentPreviewRowCount()); + if (count > 0 && position < countSum) return VIEW_TYPE_CONTENT_PREVIEW; + + countSum += (count = getProfileRowCount()); if (count > 0 && position < countSum) return VIEW_TYPE_PROFILE; countSum += (count = getServiceTargetRowCount()); @@ -3082,7 +3148,7 @@ public class ChooserActivity extends ResolverActivity implements } int getListPosition(int position) { - position -= getProfileRowCount(); + position -= getContentPreviewRowCount() + getProfileRowCount(); final int serviceCount = mChooserListAdapter.getServiceTargetCount(); final int serviceRows = (int) Math.ceil((float) serviceCount diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java index 9488e4f3b297e..7a0afa2036f69 100644 --- a/core/java/com/android/internal/app/IntentForwarderActivity.java +++ b/core/java/com/android/internal/app/IntentForwarderActivity.java @@ -26,6 +26,7 @@ import android.app.ActivityThread; import android.app.AppGlobals; import android.app.admin.DevicePolicyManager; import android.compat.annotation.UnsupportedAppUsage; +import android.content.ContentResolver; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.IPackageManager; @@ -108,7 +109,8 @@ public class IntentForwarderActivity extends Activity { } final int callingUserId = getUserId(); - final Intent newIntent = canForward(intentReceived, targetUserId); + final Intent newIntent = canForward(intentReceived, getUserId(), targetUserId, + mInjector.getIPackageManager(), getContentResolver()); if (newIntent != null) { if (Intent.ACTION_CHOOSER.equals(newIntent.getAction())) { Intent innerIntent = newIntent.getParcelableExtra(Intent.EXTRA_INTENT); @@ -191,7 +193,8 @@ public class IntentForwarderActivity extends Activity { * Check whether the intent can be forwarded to target user. Return the intent used for * forwarding if it can be forwarded, {@code null} otherwise. */ - Intent canForward(Intent incomingIntent, int targetUserId) { + static Intent canForward(Intent incomingIntent, int sourceUserId, int targetUserId, + IPackageManager packageManager, ContentResolver contentResolver) { Intent forwardIntent = new Intent(incomingIntent); forwardIntent.addFlags( Intent.FLAG_ACTIVITY_FORWARD_RESULT | Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP); @@ -220,11 +223,11 @@ public class IntentForwarderActivity extends Activity { if (forwardIntent.getSelector() != null) { intentToCheck = forwardIntent.getSelector(); } - String resolvedType = intentToCheck.resolveTypeIfNeeded(getContentResolver()); + String resolvedType = intentToCheck.resolveTypeIfNeeded(contentResolver); sanitizeIntent(intentToCheck); try { - if (mInjector.getIPackageManager(). - canForwardTo(intentToCheck, resolvedType, getUserId(), targetUserId)) { + if (packageManager.canForwardTo( + intentToCheck, resolvedType, sourceUserId, targetUserId)) { return forwardIntent; } } catch (RemoteException e) { @@ -267,7 +270,7 @@ public class IntentForwarderActivity extends Activity { /** * Sanitize the intent in place. */ - private void sanitizeIntent(Intent intent) { + private static void sanitizeIntent(Intent intent) { // Apps should not be allowed to target a specific package/ component in the target user. intent.setPackage(null); intent.setComponent(null); diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index a934de3289896..022573c5203a6 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -387,6 +387,11 @@ public class ResolverActivity extends Activity implements | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); rdl.setOnApplyWindowInsetsListener(this::onApplyWindowInsets); + rdl.setMaxCollapsedHeight(hasWorkProfile() && ENABLE_TABBED_VIEW + ? getResources().getDimensionPixelSize( + R.dimen.resolver_empty_state_height_with_tabs) + : getResources().getDimensionPixelSize(R.dimen.resolver_empty_state_height)); + mResolverDrawerLayout = rdl; } @@ -548,13 +553,6 @@ public class ResolverActivity extends Activity implements applyFooterView(mSystemWindowInsets.bottom); } - View emptyView = findViewById(R.id.empty); - if (emptyView != null) { - emptyView.setPadding(0, 0, 0, mSystemWindowInsets.bottom - + getResources().getDimensionPixelSize( - R.dimen.chooser_edge_margin_normal) * 2); - } - return insets.consumeSystemWindowInsets(); } @@ -941,10 +939,13 @@ public class ResolverActivity extends Activity implements } @Override // ResolverListCommunicator - public void onPostListReady(ResolverListAdapter listAdapter, boolean doPostProcessing) { + public final void onPostListReady(ResolverListAdapter listAdapter, boolean doPostProcessing) { if (isAutolaunching() || maybeAutolaunchActivity()) { return; } + if (shouldShowEmptyState(listAdapter)) { + mMultiProfilePagerAdapter.showEmptyState(listAdapter); + } if (doPostProcessing) { if (mMultiProfilePagerAdapter.getCurrentUserHandle().getIdentifier() == UserHandle.myUserId()) { @@ -1497,15 +1498,17 @@ public class ResolverActivity extends Activity implements } private void setupViewVisibilities() { - int count = mMultiProfilePagerAdapter.getActiveListAdapter().getUnfilteredCount(); - boolean shouldShowEmptyState = count == 0 - && mMultiProfilePagerAdapter.getActiveListAdapter().getPlaceholderCount() == 0; - //TODO(arangelov): Handle empty state - if (!shouldShowEmptyState) { - addUseDifferentAppLabelIfNecessary(mMultiProfilePagerAdapter.getActiveListAdapter()); + ResolverListAdapter activeListAdapter = mMultiProfilePagerAdapter.getActiveListAdapter(); + if (!shouldShowEmptyState(activeListAdapter)) { + addUseDifferentAppLabelIfNecessary(activeListAdapter); } } + private boolean shouldShowEmptyState(ResolverListAdapter listAdapter) { + int count = listAdapter.getUnfilteredCount(); + return count == 0 && listAdapter.getPlaceholderCount() == 0; + } + /** * Add a label to signify that the user can pick a different app. * @param adapter The adapter used to provide data to item views. diff --git a/core/java/com/android/internal/app/ResolverListAdapter.java b/core/java/com/android/internal/app/ResolverListAdapter.java index 2321da14cebe1..ea8409058264d 100644 --- a/core/java/com/android/internal/app/ResolverListAdapter.java +++ b/core/java/com/android/internal/app/ResolverListAdapter.java @@ -607,6 +607,10 @@ public class ResolverListAdapter extends BaseAdapter { mIntents, userHandle); } + protected List getIntents() { + return mIntents; + } + /** * Necessary methods to communicate between {@link ResolverListAdapter} * and {@link ResolverActivity}. diff --git a/core/java/com/android/internal/app/ResolverViewPager.java b/core/java/com/android/internal/app/ResolverViewPager.java index 8ec94f159725e..84fed9c5ee90a 100644 --- a/core/java/com/android/internal/app/ResolverViewPager.java +++ b/core/java/com/android/internal/app/ResolverViewPager.java @@ -57,10 +57,15 @@ public class ResolverViewPager extends ViewPager { widthMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY); int height = getMeasuredHeight(); if (getChildCount() > 0) { - View firstChild = getChildAt(0); - firstChild.measure(widthMeasureSpec, + View child = getChildAt(0); + child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST)); - height = firstChild.getMeasuredHeight(); + if (height > child.getMeasuredHeight()) { + height = child.getMeasuredHeight(); + } + } + if (height < getMinimumHeight()) { + height = getMinimumHeight(); } heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY); super.onMeasure(widthMeasureSpec, heightMeasureSpec); diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java index e0c3823b40eff..b117e40cdbb67 100644 --- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java +++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java @@ -66,6 +66,12 @@ public class ResolverDrawerLayout extends ViewGroup { */ private int mMaxCollapsedHeightSmall; + /** + * Whether {@code mMaxCollapsedHeightSmall} was set explicitly as a layout attribute or + * inferred by {@code mMaxCollapsedHeight}. + */ + private final boolean mIsMaxCollapsedHeightSmallExplicit; + private boolean mSmallCollapsed; /** @@ -146,6 +152,8 @@ public class ResolverDrawerLayout extends ViewGroup { mMaxCollapsedHeightSmall = a.getDimensionPixelSize( R.styleable.ResolverDrawerLayout_maxCollapsedHeightSmall, mMaxCollapsedHeight); + mIsMaxCollapsedHeightSmallExplicit = + a.hasValue(R.styleable.ResolverDrawerLayout_maxCollapsedHeightSmall); mShowAtTop = a.getBoolean(R.styleable.ResolverDrawerLayout_showAtTop, false); a.recycle(); @@ -162,6 +170,21 @@ public class ResolverDrawerLayout extends ViewGroup { setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); } + /** + * Dynamically set the max collapsed height. Note this also updates the small collapsed + * height if it wasn't specified explicitly. + */ + public void setMaxCollapsedHeight(int heightInPixels) { + if (heightInPixels == mMaxCollapsedHeight) { + return; + } + mMaxCollapsedHeight = heightInPixels; + if (!mIsMaxCollapsedHeightSmallExplicit) { + mMaxCollapsedHeightSmall = mMaxCollapsedHeight; + } + requestLayout(); + } + public void setSmallCollapsed(boolean smallCollapsed) { mSmallCollapsed = smallCollapsed; requestLayout(); diff --git a/core/res/res/drawable/ic_no_apps.xml b/core/res/res/drawable/ic_no_apps.xml new file mode 100644 index 0000000000000..4d296bddd8137 --- /dev/null +++ b/core/res/res/drawable/ic_no_apps.xml @@ -0,0 +1,4 @@ + + + diff --git a/core/res/res/drawable/ic_sharing_disabled.xml b/core/res/res/drawable/ic_sharing_disabled.xml new file mode 100644 index 0000000000000..d488cdbb8b7b9 --- /dev/null +++ b/core/res/res/drawable/ic_sharing_disabled.xml @@ -0,0 +1,4 @@ + + + diff --git a/core/res/res/drawable/ic_work_apps_off.xml b/core/res/res/drawable/ic_work_apps_off.xml new file mode 100644 index 0000000000000..e91806f199dff --- /dev/null +++ b/core/res/res/drawable/ic_work_apps_off.xml @@ -0,0 +1,4 @@ + + + diff --git a/core/res/res/layout/chooser_grid.xml b/core/res/res/layout/chooser_grid.xml index 4e8a41f81c48c..24a21ebcad800 100644 --- a/core/res/res/layout/chooser_grid.xml +++ b/core/res/res/layout/chooser_grid.xml @@ -75,7 +75,8 @@ + android:layout_height="wrap_content" + android:visibility="gone"> - - diff --git a/core/res/res/layout/chooser_list_per_profile.xml b/core/res/res/layout/chooser_list_per_profile.xml index 212813f10bd47..38b1b529458cb 100644 --- a/core/res/res/layout/chooser_list_per_profile.xml +++ b/core/res/res/layout/chooser_list_per_profile.xml @@ -13,15 +13,21 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> - - \ No newline at end of file + android:layout_marginTop="8dp"> + + + + \ No newline at end of file diff --git a/core/res/res/layout/resolver_empty_states.xml b/core/res/res/layout/resolver_empty_states.xml new file mode 100644 index 0000000000000..6959e9c0f2bb9 --- /dev/null +++ b/core/res/res/layout/resolver_empty_states.xml @@ -0,0 +1,58 @@ + + + + + + +