1 /*
2  * Copyright (C) 2022 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.providers.media.photopicker.ui.settings;
18 
19 import static com.android.providers.media.photopicker.ui.settings.SettingsCloudMediaSelectFragment.EXTRA_TAB_USER_ID;
20 
21 import android.annotation.NonNull;
22 import android.annotation.UserIdInt;
23 import android.app.ActivityManager;
24 import android.content.Context;
25 import android.os.Bundle;
26 import android.view.View;
27 
28 import androidx.fragment.app.Fragment;
29 import androidx.lifecycle.ViewModelProvider;
30 
31 import com.android.modules.utils.build.SdkLevel;
32 import com.android.providers.media.photopicker.data.model.UserId;
33 import com.android.settingslib.widget.ProfileSelectFragment;
34 import com.android.settingslib.widget.profileselector.R;
35 
36 import com.google.android.material.tabs.TabLayout;
37 
38 import java.util.ArrayList;
39 import java.util.List;
40 
41 /**
42  * This fragment will display swipable "Personal" and "Work" tabs on the settings page.
43  */
44 public class SettingsProfileSelectFragment extends ProfileSelectFragment {
45     @NonNull
46     private SettingsViewModel mSettingsViewModel;
47     @NonNull
48     private TabLayout mTabLayout;
49     private static boolean sUserIdProvided = false;
50     private static List<Integer> sUserIdListToShowProfileTabs = new ArrayList<>();
51 
52     @Override
onAttach(@onNull Context context)53     public void onAttach(@NonNull Context context) {
54         super.onAttach(context);
55 
56         mSettingsViewModel =
57                 new ViewModelProvider(requireActivity()).get(SettingsViewModel.class);
58     }
59 
60     @Override
onViewCreated(View view, Bundle savedInstanceState)61     public void onViewCreated(View view, Bundle savedInstanceState) {
62         super.onViewCreated(view, savedInstanceState);
63 
64         mTabLayout = getTabLayout(view);
65     }
66 
67     @Override
createFragment(int tabUserIdOrPosition)68     public Fragment createFragment(int tabUserIdOrPosition) {
69         final int userId = getTabUserId(tabUserIdOrPosition);
70 
71         return getCloudMediaSelectFragment(userId);
72     }
73 
74     @Override
onPause()75     public void onPause() {
76         super.onPause();
77 
78         // Save selected tab state in ViewModel.
79         final int selectedTab = mTabLayout.getSelectedTabPosition();
80         mSettingsViewModel.setSelectedTab(selectedTab);
81     }
82 
83     @Override
onResume()84     public void onResume() {
85         super.onResume();
86 
87         // Set selected tab according to saved state.
88         final int previouslySelectedTab = mSettingsViewModel.getSelectedTab();
89         final int tabCount = mTabLayout.getTabCount();
90         // Skip tab selection if no tab was selected or if previously selected tab was not found
91         if (previouslySelectedTab < tabCount
92                 && previouslySelectedTab != SettingsViewModel.TAB_NOT_SET) {
93             // Selected tab state has previously been set in onPause() and we should restore it.
94             mTabLayout.getTabAt(previouslySelectedTab).select();
95         }
96     }
97 
98     /**
99      * Create an instance of {@link SettingsCloudMediaSelectFragment}.
100      *
101      * @param userId User will be able to view and update cloud media providers in
102      * {@link SettingsCloudMediaSelectFragment} for the given userId.
103      * @return {@link SettingsCloudMediaSelectFragment} for given userId.
104      */
105     @NonNull
getCloudMediaSelectFragment( @serIdInt int userId)106     public static SettingsCloudMediaSelectFragment getCloudMediaSelectFragment(
107             @UserIdInt int userId) {
108         // Add extras to communicate the fragment can choose cloud media provider for which userId.
109         final SettingsCloudMediaSelectFragment fragment = new SettingsCloudMediaSelectFragment();
110         final Bundle extras = new Bundle();
111         extras.putInt(EXTRA_TAB_USER_ID, userId);
112         fragment.setArguments(extras);
113 
114         return fragment;
115     }
116 
117     /**
118      * Create an instance of {@link SettingsProfileSelectFragment}.
119      *
120      * @param selectedProfileTab is the tab position id or the tab's UserId that should be selected
121      *                           when the user first lands on the settings page.
122      * @return A new {@link SettingsProfileSelectFragment} object.
123      */
124     @NonNull
getProfileSelectFragment(int selectedProfileTab, boolean userIdProvided, List<Integer> userIdListToShowProfileTabs)125     public static SettingsProfileSelectFragment getProfileSelectFragment(int selectedProfileTab,
126             boolean userIdProvided, List<Integer> userIdListToShowProfileTabs) {
127         final SettingsProfileSelectFragment fragment = new SettingsProfileSelectFragment();
128         final Bundle extras = new Bundle();
129         if (userIdProvided) {
130             sUserIdProvided = true;
131             sUserIdListToShowProfileTabs = userIdListToShowProfileTabs;
132             extras.putInt(EXTRA_SHOW_FRAGMENT_USER_ID, selectedProfileTab);
133             extras.putIntegerArrayList(EXTRA_LIST_OF_USER_IDS,
134                     new ArrayList<>(userIdListToShowProfileTabs));
135         } else {
136             extras.putInt(EXTRA_SHOW_FRAGMENT_TAB, selectedProfileTab);
137         }
138         fragment.setArguments(extras);
139         return fragment;
140     }
141 
getManagedUser()142     private int getManagedUser() {
143         if (mSettingsViewModel.getConfigStore().isPrivateSpaceInPhotoPickerEnabled()
144                 && SdkLevel.isAtLeastS()) {
145             for (UserId userId : mSettingsViewModel.getUserManagerState().getAllUserProfileIds()) {
146                 if (mSettingsViewModel.getUserManagerState().isManagedUserProfile(userId)) {
147                     return userId.getIdentifier();
148                 }
149             }
150         } else {
151             return mSettingsViewModel.getUserIdManager().getManagedUserId().getIdentifier();
152         }
153         return -1;
154     }
155 
156     @UserIdInt
getTabUserId(int tabUserIdOrPosition)157     private int getTabUserId(int tabUserIdOrPosition) {
158         if (sUserIdProvided) {
159             final int userId = tabUserIdOrPosition;
160             if (!sUserIdListToShowProfileTabs.contains(userId)) {
161                 throw new IllegalArgumentException("Unidentified user id " + tabUserIdOrPosition);
162             }
163             return userId;
164         }
165         int personalUser = ActivityManager.getCurrentUser();
166         int managedUser = getManagedUser();
167         switch (tabUserIdOrPosition) {
168             case ProfileSelectFragment.PERSONAL_TAB:
169                 return personalUser;
170             case ProfileSelectFragment.WORK_TAB:
171                 return managedUser;
172             default:
173                 // tabUserIdOrPosition should match one of the cases above.
174                 throw new IllegalArgumentException("Unidentified tab id " + tabUserIdOrPosition);
175         }
176     }
177 
178     @NonNull
getTabLayout(@onNull View view)179     private TabLayout getTabLayout(@NonNull View view) {
180         final View tabContainer = view.findViewById(R.id.tab_container);
181 
182         return tabContainer.findViewById(R.id.tabs);
183     }
184 }
185