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.internal.app; 18 19 import android.annotation.Nullable; 20 import android.content.Context; 21 import android.os.UserHandle; 22 import android.view.LayoutInflater; 23 import android.view.View; 24 import android.view.ViewGroup; 25 26 import com.android.internal.R; 27 import com.android.internal.annotations.VisibleForTesting; 28 import com.android.internal.widget.GridLayoutManager; 29 import com.android.internal.widget.PagerAdapter; 30 import com.android.internal.widget.RecyclerView; 31 32 /** 33 * A {@link PagerAdapter} which describes the work and personal profile share sheet screens. 34 */ 35 @VisibleForTesting 36 public class ChooserMultiProfilePagerAdapter extends AbstractMultiProfilePagerAdapter { 37 private static final int SINGLE_CELL_SPAN_SIZE = 1; 38 39 private final ChooserProfileDescriptor[] mItems; 40 private final boolean mIsSendAction; 41 private int mBottomOffset; 42 private int mMaxTargetsPerRow; 43 ChooserMultiProfilePagerAdapter(Context context, ChooserActivity.ChooserGridAdapter adapter, UserHandle personalProfileUserHandle, UserHandle workProfileUserHandle, boolean isSendAction, int maxTargetsPerRow)44 ChooserMultiProfilePagerAdapter(Context context, 45 ChooserActivity.ChooserGridAdapter adapter, 46 UserHandle personalProfileUserHandle, 47 UserHandle workProfileUserHandle, 48 boolean isSendAction, int maxTargetsPerRow) { 49 super(context, /* currentPage */ 0, personalProfileUserHandle, workProfileUserHandle); 50 mItems = new ChooserProfileDescriptor[] { 51 createProfileDescriptor(adapter) 52 }; 53 mIsSendAction = isSendAction; 54 mMaxTargetsPerRow = maxTargetsPerRow; 55 } 56 ChooserMultiProfilePagerAdapter(Context context, ChooserActivity.ChooserGridAdapter personalAdapter, ChooserActivity.ChooserGridAdapter workAdapter, @Profile int defaultProfile, UserHandle personalProfileUserHandle, UserHandle workProfileUserHandle, boolean isSendAction, int maxTargetsPerRow)57 ChooserMultiProfilePagerAdapter(Context context, 58 ChooserActivity.ChooserGridAdapter personalAdapter, 59 ChooserActivity.ChooserGridAdapter workAdapter, 60 @Profile int defaultProfile, 61 UserHandle personalProfileUserHandle, 62 UserHandle workProfileUserHandle, 63 boolean isSendAction, int maxTargetsPerRow) { 64 super(context, /* currentPage */ defaultProfile, personalProfileUserHandle, 65 workProfileUserHandle); 66 mItems = new ChooserProfileDescriptor[] { 67 createProfileDescriptor(personalAdapter), 68 createProfileDescriptor(workAdapter) 69 }; 70 mIsSendAction = isSendAction; 71 mMaxTargetsPerRow = maxTargetsPerRow; 72 } 73 createProfileDescriptor( ChooserActivity.ChooserGridAdapter adapter)74 private ChooserProfileDescriptor createProfileDescriptor( 75 ChooserActivity.ChooserGridAdapter adapter) { 76 final LayoutInflater inflater = LayoutInflater.from(getContext()); 77 final ViewGroup rootView = 78 (ViewGroup) inflater.inflate(R.layout.chooser_list_per_profile, null, false); 79 return new ChooserProfileDescriptor(rootView, adapter); 80 } 81 getListViewForIndex(int index)82 RecyclerView getListViewForIndex(int index) { 83 return getItem(index).recyclerView; 84 } 85 86 @Override getItem(int pageIndex)87 ChooserProfileDescriptor getItem(int pageIndex) { 88 return mItems[pageIndex]; 89 } 90 91 @Override getItemCount()92 int getItemCount() { 93 return mItems.length; 94 } 95 96 @Override 97 @VisibleForTesting getAdapterForIndex(int pageIndex)98 public ChooserActivity.ChooserGridAdapter getAdapterForIndex(int pageIndex) { 99 return mItems[pageIndex].chooserGridAdapter; 100 } 101 102 @Override 103 @Nullable getListAdapterForUserHandle(UserHandle userHandle)104 ChooserListAdapter getListAdapterForUserHandle(UserHandle userHandle) { 105 if (getActiveListAdapter().getUserHandle().equals(userHandle)) { 106 return getActiveListAdapter(); 107 } else if (getInactiveListAdapter() != null 108 && getInactiveListAdapter().getUserHandle().equals(userHandle)) { 109 return getInactiveListAdapter(); 110 } 111 return null; 112 } 113 114 @Override setupListAdapter(int pageIndex)115 void setupListAdapter(int pageIndex) { 116 final RecyclerView recyclerView = getItem(pageIndex).recyclerView; 117 ChooserActivity.ChooserGridAdapter chooserGridAdapter = 118 getItem(pageIndex).chooserGridAdapter; 119 GridLayoutManager glm = (GridLayoutManager) recyclerView.getLayoutManager(); 120 glm.setSpanCount(mMaxTargetsPerRow); 121 glm.setSpanSizeLookup( 122 new GridLayoutManager.SpanSizeLookup() { 123 @Override 124 public int getSpanSize(int position) { 125 return chooserGridAdapter.shouldCellSpan(position) 126 ? SINGLE_CELL_SPAN_SIZE 127 : glm.getSpanCount(); 128 } 129 }); 130 } 131 132 @Override 133 @VisibleForTesting getActiveListAdapter()134 public ChooserListAdapter getActiveListAdapter() { 135 return getAdapterForIndex(getCurrentPage()).getListAdapter(); 136 } 137 138 @Override 139 @VisibleForTesting getInactiveListAdapter()140 public ChooserListAdapter getInactiveListAdapter() { 141 if (getCount() == 1) { 142 return null; 143 } 144 return getAdapterForIndex(1 - getCurrentPage()).getListAdapter(); 145 } 146 147 @Override getPersonalListAdapter()148 public ResolverListAdapter getPersonalListAdapter() { 149 return getAdapterForIndex(PROFILE_PERSONAL).getListAdapter(); 150 } 151 152 @Override 153 @Nullable getWorkListAdapter()154 public ResolverListAdapter getWorkListAdapter() { 155 return getAdapterForIndex(PROFILE_WORK).getListAdapter(); 156 } 157 158 @Override getCurrentRootAdapter()159 ChooserActivity.ChooserGridAdapter getCurrentRootAdapter() { 160 return getAdapterForIndex(getCurrentPage()); 161 } 162 163 @Override getActiveAdapterView()164 RecyclerView getActiveAdapterView() { 165 return getListViewForIndex(getCurrentPage()); 166 } 167 168 @Override 169 @Nullable getInactiveAdapterView()170 RecyclerView getInactiveAdapterView() { 171 if (getCount() == 1) { 172 return null; 173 } 174 return getListViewForIndex(1 - getCurrentPage()); 175 } 176 177 @Override getMetricsCategory()178 String getMetricsCategory() { 179 return ResolverActivity.METRICS_CATEGORY_CHOOSER; 180 } 181 182 @Override showWorkProfileOffEmptyState(ResolverListAdapter activeListAdapter, View.OnClickListener listener)183 protected void showWorkProfileOffEmptyState(ResolverListAdapter activeListAdapter, 184 View.OnClickListener listener) { 185 showEmptyState(activeListAdapter, 186 R.drawable.ic_work_apps_off, 187 R.string.resolver_turn_on_work_apps, 188 /* subtitleRes */ 0, 189 listener); 190 } 191 192 @Override showNoPersonalToWorkIntentsEmptyState(ResolverListAdapter activeListAdapter)193 protected void showNoPersonalToWorkIntentsEmptyState(ResolverListAdapter activeListAdapter) { 194 if (mIsSendAction) { 195 showEmptyState(activeListAdapter, 196 R.drawable.ic_sharing_disabled, 197 R.string.resolver_cross_profile_blocked, 198 R.string.resolver_cant_share_with_work_apps_explanation); 199 } else { 200 showEmptyState(activeListAdapter, 201 R.drawable.ic_sharing_disabled, 202 R.string.resolver_cross_profile_blocked, 203 R.string.resolver_cant_access_work_apps_explanation); 204 } 205 } 206 207 @Override showNoWorkToPersonalIntentsEmptyState(ResolverListAdapter activeListAdapter)208 protected void showNoWorkToPersonalIntentsEmptyState(ResolverListAdapter activeListAdapter) { 209 if (mIsSendAction) { 210 showEmptyState(activeListAdapter, 211 R.drawable.ic_sharing_disabled, 212 R.string.resolver_cross_profile_blocked, 213 R.string.resolver_cant_share_with_personal_apps_explanation); 214 } else { 215 showEmptyState(activeListAdapter, 216 R.drawable.ic_sharing_disabled, 217 R.string.resolver_cross_profile_blocked, 218 R.string.resolver_cant_access_personal_apps_explanation); 219 } 220 } 221 222 @Override showNoPersonalAppsAvailableEmptyState(ResolverListAdapter listAdapter)223 protected void showNoPersonalAppsAvailableEmptyState(ResolverListAdapter listAdapter) { 224 showEmptyState(listAdapter, 225 R.drawable.ic_no_apps, 226 R.string.resolver_no_personal_apps_available, 227 /* subtitleRes */ 0); 228 229 } 230 231 @Override showNoWorkAppsAvailableEmptyState(ResolverListAdapter listAdapter)232 protected void showNoWorkAppsAvailableEmptyState(ResolverListAdapter listAdapter) { 233 showEmptyState(listAdapter, 234 R.drawable.ic_no_apps, 235 R.string.resolver_no_work_apps_available, 236 /* subtitleRes */ 0); 237 } 238 setEmptyStateBottomOffset(int bottomOffset)239 void setEmptyStateBottomOffset(int bottomOffset) { 240 mBottomOffset = bottomOffset; 241 } 242 243 @Override setupContainerPadding(View container)244 protected void setupContainerPadding(View container) { 245 int initialBottomPadding = getContext().getResources().getDimensionPixelSize( 246 R.dimen.resolver_empty_state_container_padding_bottom); 247 container.setPadding(container.getPaddingLeft(), container.getPaddingTop(), 248 container.getPaddingRight(), initialBottomPadding + mBottomOffset); 249 } 250 251 class ChooserProfileDescriptor extends ProfileDescriptor { 252 private ChooserActivity.ChooserGridAdapter chooserGridAdapter; 253 private RecyclerView recyclerView; ChooserProfileDescriptor(ViewGroup rootView, ChooserActivity.ChooserGridAdapter adapter)254 ChooserProfileDescriptor(ViewGroup rootView, ChooserActivity.ChooserGridAdapter adapter) { 255 super(rootView); 256 chooserGridAdapter = adapter; 257 recyclerView = rootView.findViewById(R.id.resolver_list); 258 } 259 } 260 } 261