1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.intentresolver; 18 19 import android.content.Context; 20 import android.os.UserHandle; 21 import android.view.LayoutInflater; 22 import android.view.ViewGroup; 23 24 import androidx.recyclerview.widget.GridLayoutManager; 25 import androidx.recyclerview.widget.RecyclerView; 26 import androidx.viewpager.widget.PagerAdapter; 27 28 import com.android.intentresolver.grid.ChooserGridAdapter; 29 import com.android.intentresolver.measurements.Tracer; 30 import com.android.internal.annotations.VisibleForTesting; 31 32 import com.google.common.collect.ImmutableList; 33 34 import java.util.Optional; 35 import java.util.function.Supplier; 36 37 /** 38 * A {@link PagerAdapter} which describes the work and personal profile share sheet screens. 39 */ 40 @VisibleForTesting 41 public class ChooserMultiProfilePagerAdapter extends GenericMultiProfilePagerAdapter< 42 RecyclerView, ChooserGridAdapter, ChooserListAdapter> { 43 private static final int SINGLE_CELL_SPAN_SIZE = 1; 44 45 private final ChooserProfileAdapterBinder mAdapterBinder; 46 private final BottomPaddingOverrideSupplier mBottomPaddingOverrideSupplier; 47 ChooserMultiProfilePagerAdapter( Context context, ChooserGridAdapter adapter, EmptyStateProvider emptyStateProvider, Supplier<Boolean> workProfileQuietModeChecker, UserHandle workProfileUserHandle, UserHandle cloneProfileUserHandle, int maxTargetsPerRow)48 ChooserMultiProfilePagerAdapter( 49 Context context, 50 ChooserGridAdapter adapter, 51 EmptyStateProvider emptyStateProvider, 52 Supplier<Boolean> workProfileQuietModeChecker, 53 UserHandle workProfileUserHandle, 54 UserHandle cloneProfileUserHandle, 55 int maxTargetsPerRow) { 56 this( 57 context, 58 new ChooserProfileAdapterBinder(maxTargetsPerRow), 59 ImmutableList.of(adapter), 60 emptyStateProvider, 61 workProfileQuietModeChecker, 62 /* defaultProfile= */ 0, 63 workProfileUserHandle, 64 cloneProfileUserHandle, 65 new BottomPaddingOverrideSupplier(context)); 66 } 67 ChooserMultiProfilePagerAdapter( Context context, ChooserGridAdapter personalAdapter, ChooserGridAdapter workAdapter, EmptyStateProvider emptyStateProvider, Supplier<Boolean> workProfileQuietModeChecker, @Profile int defaultProfile, UserHandle workProfileUserHandle, UserHandle cloneProfileUserHandle, int maxTargetsPerRow)68 ChooserMultiProfilePagerAdapter( 69 Context context, 70 ChooserGridAdapter personalAdapter, 71 ChooserGridAdapter workAdapter, 72 EmptyStateProvider emptyStateProvider, 73 Supplier<Boolean> workProfileQuietModeChecker, 74 @Profile int defaultProfile, 75 UserHandle workProfileUserHandle, 76 UserHandle cloneProfileUserHandle, 77 int maxTargetsPerRow) { 78 this( 79 context, 80 new ChooserProfileAdapterBinder(maxTargetsPerRow), 81 ImmutableList.of(personalAdapter, workAdapter), 82 emptyStateProvider, 83 workProfileQuietModeChecker, 84 defaultProfile, 85 workProfileUserHandle, 86 cloneProfileUserHandle, 87 new BottomPaddingOverrideSupplier(context)); 88 } 89 ChooserMultiProfilePagerAdapter( Context context, ChooserProfileAdapterBinder adapterBinder, ImmutableList<ChooserGridAdapter> gridAdapters, EmptyStateProvider emptyStateProvider, Supplier<Boolean> workProfileQuietModeChecker, @Profile int defaultProfile, UserHandle workProfileUserHandle, UserHandle cloneProfileUserHandle, BottomPaddingOverrideSupplier bottomPaddingOverrideSupplier)90 private ChooserMultiProfilePagerAdapter( 91 Context context, 92 ChooserProfileAdapterBinder adapterBinder, 93 ImmutableList<ChooserGridAdapter> gridAdapters, 94 EmptyStateProvider emptyStateProvider, 95 Supplier<Boolean> workProfileQuietModeChecker, 96 @Profile int defaultProfile, 97 UserHandle workProfileUserHandle, 98 UserHandle cloneProfileUserHandle, 99 BottomPaddingOverrideSupplier bottomPaddingOverrideSupplier) { 100 super( 101 context, 102 gridAdapter -> gridAdapter.getListAdapter(), 103 adapterBinder, 104 gridAdapters, 105 emptyStateProvider, 106 workProfileQuietModeChecker, 107 defaultProfile, 108 workProfileUserHandle, 109 cloneProfileUserHandle, 110 () -> makeProfileView(context), 111 bottomPaddingOverrideSupplier); 112 mAdapterBinder = adapterBinder; 113 mBottomPaddingOverrideSupplier = bottomPaddingOverrideSupplier; 114 } 115 setMaxTargetsPerRow(int maxTargetsPerRow)116 public void setMaxTargetsPerRow(int maxTargetsPerRow) { 117 mAdapterBinder.setMaxTargetsPerRow(maxTargetsPerRow); 118 } 119 setEmptyStateBottomOffset(int bottomOffset)120 public void setEmptyStateBottomOffset(int bottomOffset) { 121 mBottomPaddingOverrideSupplier.setEmptyStateBottomOffset(bottomOffset); 122 } 123 124 /** 125 * Notify adapter about the drawer's collapse state. This will affect the app divider's 126 * visibility. 127 */ setIsCollapsed(boolean isCollapsed)128 public void setIsCollapsed(boolean isCollapsed) { 129 for (int i = 0, size = getItemCount(); i < size; i++) { 130 getAdapterForIndex(i).setAzLabelVisibility(!isCollapsed); 131 } 132 } 133 makeProfileView(Context context)134 private static ViewGroup makeProfileView(Context context) { 135 LayoutInflater inflater = LayoutInflater.from(context); 136 ViewGroup rootView = (ViewGroup) inflater.inflate( 137 R.layout.chooser_list_per_profile, null, false); 138 RecyclerView recyclerView = rootView.findViewById(com.android.internal.R.id.resolver_list); 139 recyclerView.setAccessibilityDelegateCompat( 140 new ChooserRecyclerViewAccessibilityDelegate(recyclerView)); 141 return rootView; 142 } 143 144 @Override rebuildActiveTab(boolean doPostProcessing)145 boolean rebuildActiveTab(boolean doPostProcessing) { 146 if (doPostProcessing) { 147 Tracer.INSTANCE.beginAppTargetLoadingSection(getActiveListAdapter().getUserHandle()); 148 } 149 return super.rebuildActiveTab(doPostProcessing); 150 } 151 152 @Override rebuildInactiveTab(boolean doPostProcessing)153 boolean rebuildInactiveTab(boolean doPostProcessing) { 154 if (getItemCount() != 1 && doPostProcessing) { 155 Tracer.INSTANCE.beginAppTargetLoadingSection(getInactiveListAdapter().getUserHandle()); 156 } 157 return super.rebuildInactiveTab(doPostProcessing); 158 } 159 160 private static class BottomPaddingOverrideSupplier implements Supplier<Optional<Integer>> { 161 private final Context mContext; 162 private int mBottomOffset; 163 BottomPaddingOverrideSupplier(Context context)164 BottomPaddingOverrideSupplier(Context context) { 165 mContext = context; 166 } 167 setEmptyStateBottomOffset(int bottomOffset)168 public void setEmptyStateBottomOffset(int bottomOffset) { 169 mBottomOffset = bottomOffset; 170 } 171 get()172 public Optional<Integer> get() { 173 int initialBottomPadding = mContext.getResources().getDimensionPixelSize( 174 R.dimen.resolver_empty_state_container_padding_bottom); 175 return Optional.of(initialBottomPadding + mBottomOffset); 176 } 177 } 178 179 private static class ChooserProfileAdapterBinder implements 180 AdapterBinder<RecyclerView, ChooserGridAdapter> { 181 private int mMaxTargetsPerRow; 182 ChooserProfileAdapterBinder(int maxTargetsPerRow)183 ChooserProfileAdapterBinder(int maxTargetsPerRow) { 184 mMaxTargetsPerRow = maxTargetsPerRow; 185 } 186 setMaxTargetsPerRow(int maxTargetsPerRow)187 public void setMaxTargetsPerRow(int maxTargetsPerRow) { 188 mMaxTargetsPerRow = maxTargetsPerRow; 189 } 190 191 @Override bind( RecyclerView recyclerView, ChooserGridAdapter chooserGridAdapter)192 public void bind( 193 RecyclerView recyclerView, ChooserGridAdapter chooserGridAdapter) { 194 GridLayoutManager glm = (GridLayoutManager) recyclerView.getLayoutManager(); 195 glm.setSpanCount(mMaxTargetsPerRow); 196 glm.setSpanSizeLookup( 197 new GridLayoutManager.SpanSizeLookup() { 198 @Override 199 public int getSpanSize(int position) { 200 return chooserGridAdapter.shouldCellSpan(position) 201 ? SINGLE_CELL_SPAN_SIZE 202 : glm.getSpanCount(); 203 } 204 }); 205 } 206 } 207 } 208