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.settings.dashboard.profileselector; 18 19 import static android.content.Intent.EXTRA_USER_ID; 20 21 import android.annotation.IntDef; 22 import android.app.Activity; 23 import android.content.Context; 24 import android.os.Bundle; 25 import android.os.UserHandle; 26 import android.os.UserManager; 27 import android.text.TextUtils; 28 import android.view.LayoutInflater; 29 import android.view.View; 30 import android.view.ViewGroup; 31 import android.widget.FrameLayout; 32 import android.widget.LinearLayout; 33 34 import androidx.annotation.VisibleForTesting; 35 import androidx.fragment.app.Fragment; 36 import androidx.fragment.app.FragmentStatePagerAdapter; 37 import androidx.recyclerview.widget.RecyclerView; 38 import androidx.viewpager.widget.ViewPager; 39 40 import com.android.settings.R; 41 import com.android.settings.SettingsActivity; 42 import com.android.settings.Utils; 43 import com.android.settings.dashboard.DashboardFragment; 44 45 import com.google.android.material.tabs.TabLayout; 46 47 import java.lang.annotation.Retention; 48 import java.lang.annotation.RetentionPolicy; 49 import java.util.Locale; 50 51 /** 52 * Base fragment class for profile settings. 53 */ 54 public abstract class ProfileSelectFragment extends DashboardFragment { 55 56 private static final String TAG = "ProfileSelectFragment"; 57 58 /** 59 * Denotes the profile type. 60 */ 61 @Retention(RetentionPolicy.SOURCE) 62 @IntDef({ 63 ProfileType.PERSONAL, 64 ProfileType.WORK, 65 ProfileType.ALL 66 }) 67 public @interface ProfileType { 68 /** 69 * It is personal work profile. 70 */ 71 int PERSONAL = 1; 72 73 /** 74 * It is work profile 75 */ 76 int WORK = 1 << 1; 77 78 /** 79 * It is personal and work profile 80 */ 81 int ALL = PERSONAL | WORK; 82 } 83 84 /** 85 * Used in fragment argument and pass {@link ProfileType} to it 86 */ 87 public static final String EXTRA_PROFILE = "profile"; 88 89 /** 90 * Used in fragment argument with Extra key {@link SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB} 91 */ 92 public static final int PERSONAL_TAB = 0; 93 94 /** 95 * Used in fragment argument with Extra key {@link SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB} 96 */ 97 public static final int WORK_TAB = 1; 98 private static final int[] LABEL = { 99 R.string.category_personal, R.string.category_work 100 }; 101 102 private ViewGroup mContentView; 103 104 @Override onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)105 public View onCreateView(LayoutInflater inflater, ViewGroup container, 106 Bundle savedInstanceState) { 107 mContentView = (ViewGroup) super.onCreateView(inflater, container, savedInstanceState); 108 final Activity activity = getActivity(); 109 final int selectedTab = convertPosition(getTabId(activity, getArguments())); 110 111 final View tabContainer = mContentView.findViewById(R.id.tab_container); 112 final ViewPager viewPager = tabContainer.findViewById(R.id.view_pager); 113 viewPager.setAdapter(new ProfileSelectFragment.ViewPagerAdapter(this)); 114 final TabLayout tabs = tabContainer.findViewById(R.id.tabs); 115 tabs.setupWithViewPager(viewPager); 116 tabContainer.setVisibility(View.VISIBLE); 117 final TabLayout.Tab tab = tabs.getTabAt(selectedTab); 118 tab.select(); 119 120 final FrameLayout listContainer = mContentView.findViewById(android.R.id.list_container); 121 listContainer.setLayoutParams(new LinearLayout.LayoutParams( 122 ViewGroup.LayoutParams.MATCH_PARENT, 123 ViewGroup.LayoutParams.WRAP_CONTENT)); 124 125 final RecyclerView recyclerView = getListView(); 126 recyclerView.setOverScrollMode(View.OVER_SCROLL_NEVER); 127 Utils.setActionBarShadowAnimation(activity, getSettingsLifecycle(), recyclerView); 128 129 return mContentView; 130 } 131 132 @Override getMetricsCategory()133 public int getMetricsCategory() { 134 return METRICS_CATEGORY_UNKNOWN; 135 } 136 137 /** 138 * Returns an array of {@link Fragment} to display in the 139 * {@link com.google.android.material.tabs.TabLayout} 140 */ getFragments()141 public abstract Fragment[] getFragments(); 142 143 @Override getPreferenceScreenResId()144 protected int getPreferenceScreenResId() { 145 return R.xml.dummy_preference_screen; 146 } 147 148 @Override getLogTag()149 protected String getLogTag() { 150 return TAG; 151 } 152 153 @VisibleForTesting getTabId(Activity activity, Bundle bundle)154 int getTabId(Activity activity, Bundle bundle) { 155 if (bundle != null) { 156 final int extraTab = bundle.getInt(SettingsActivity.EXTRA_SHOW_FRAGMENT_TAB, -1); 157 if (extraTab != -1) { 158 return extraTab; 159 } 160 final int userId = bundle.getInt(EXTRA_USER_ID, UserHandle.SYSTEM.getIdentifier()); 161 final boolean isWorkProfile = UserManager.get(activity).isManagedProfile(userId); 162 if (isWorkProfile) { 163 return WORK_TAB; 164 } 165 } 166 // Start intent from a specific user eg: adb shell --user 10 167 final int intentUser = activity.getIntent().getContentUserHint(); 168 if (UserManager.get(activity).isManagedProfile(intentUser)) { 169 return WORK_TAB; 170 } 171 172 return PERSONAL_TAB; 173 } 174 175 static class ViewPagerAdapter extends FragmentStatePagerAdapter { 176 177 private final Fragment[] mChildFragments; 178 private final Context mContext; 179 ViewPagerAdapter(ProfileSelectFragment fragment)180 ViewPagerAdapter(ProfileSelectFragment fragment) { 181 super(fragment.getChildFragmentManager()); 182 mContext = fragment.getContext(); 183 mChildFragments = fragment.getFragments(); 184 } 185 186 @Override getItem(int position)187 public Fragment getItem(int position) { 188 return mChildFragments[convertPosition(position)]; 189 } 190 191 @Override getCount()192 public int getCount() { 193 return mChildFragments.length; 194 } 195 196 @Override getPageTitle(int position)197 public CharSequence getPageTitle(int position) { 198 return mContext.getString(LABEL[convertPosition(position)]); 199 } 200 } 201 convertPosition(int index)202 private static int convertPosition(int index) { 203 if (TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) 204 == View.LAYOUT_DIRECTION_RTL) { 205 return LABEL.length - 1 - index; 206 } 207 return index; 208 } 209 } 210