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