1 /*
2  * Copyright (C) 2017 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.deviceinfo.storage;
18 
19 import android.content.Context;
20 import android.content.pm.UserInfo;
21 import android.graphics.drawable.Drawable;
22 import android.os.UserManager;
23 import android.util.SparseArray;
24 
25 import androidx.annotation.NonNull;
26 import androidx.annotation.Nullable;
27 import androidx.annotation.VisibleForTesting;
28 import androidx.preference.PreferenceGroup;
29 import androidx.preference.PreferenceScreen;
30 
31 import com.android.settings.Utils;
32 import com.android.settings.core.PreferenceControllerMixin;
33 import com.android.settings.deviceinfo.StorageItemPreference;
34 import com.android.settingslib.core.AbstractPreferenceController;
35 
36 import java.util.ArrayList;
37 import java.util.List;
38 
39 /**
40  * SecondaryUserController controls the preferences on the Storage screen which had to do with
41  * secondary users.
42  */
43 public class SecondaryUserController extends AbstractPreferenceController implements
44         PreferenceControllerMixin, StorageAsyncLoader.ResultHandler,
45         UserIconLoader.UserIconHandler {
46     // PreferenceGroupKey to try to add our preference onto.
47     private static final String TARGET_PREFERENCE_GROUP_KEY = "pref_secondary_users";
48     private static final String PREFERENCE_KEY_BASE = "pref_user_";
49     private static final int USER_PROFILE_INSERTION_LOCATION = 6;
50     private static final int SIZE_NOT_SET = -1;
51 
52     private @NonNull
53     UserInfo mUser;
54     private @Nullable
55     StorageItemPreference mStoragePreference;
56     private PreferenceGroup mPreferenceGroup;
57     private Drawable mUserIcon;
58     private long mSize;
59     private long mTotalSizeBytes;
60     private boolean mIsVisible;
61 
62     /**
63      * Adds the appropriate controllers to a controller list for handling all secondary users on
64      * a device.
65      *
66      * @param context     Context for initializing the preference controllers.
67      * @param userManager UserManagerWrapper for figuring out which controllers to add.
68      * @param isWorkProfileOnly only shows secondary users of work profile.
69      *                          (e.g., it should be true in work profile tab)
70      */
getSecondaryUserControllers( Context context, UserManager userManager, boolean isWorkProfileOnly)71     public static List<AbstractPreferenceController> getSecondaryUserControllers(
72             Context context, UserManager userManager, boolean isWorkProfileOnly) {
73 
74         List<AbstractPreferenceController> controllers = new ArrayList<>();
75         UserInfo primaryUser = userManager.getPrimaryUser();
76         boolean addedUser = false;
77         List<UserInfo> infos = userManager.getUsers();
78         for (int i = 0, size = infos.size(); i < size; i++) {
79             UserInfo info = infos.get(i);
80             if (info.isPrimary()) {
81                 continue;
82             }
83 
84             if (Utils.isProfileOf(primaryUser, info)) {
85                 continue;
86             }
87 
88             if (isWorkProfileOnly && !info.isManagedProfile()) {
89                 continue;
90             }
91 
92             controllers.add(new SecondaryUserController(context, info));
93             addedUser = true;
94         }
95 
96         if (!addedUser) {
97             controllers.add(new NoSecondaryUserController(context));
98         }
99         return controllers;
100     }
101 
102     /**
103      * Constructor for a given secondary user.
104      *
105      * @param context Context to initialize the underlying {@link AbstractPreferenceController}.
106      * @param info    {@link UserInfo} for the secondary user which this controllers covers.
107      */
108     @VisibleForTesting
SecondaryUserController(Context context, @NonNull UserInfo info)109     SecondaryUserController(Context context, @NonNull UserInfo info) {
110         super(context);
111         mUser = info;
112         mSize = SIZE_NOT_SET;
113     }
114 
115     @Override
displayPreference(PreferenceScreen screen)116     public void displayPreference(PreferenceScreen screen) {
117         if (mStoragePreference == null) {
118             mStoragePreference = new StorageItemPreference(screen.getContext());
119 
120             mPreferenceGroup = screen.findPreference(TARGET_PREFERENCE_GROUP_KEY);
121             mStoragePreference.setTitle(mUser.name);
122             mStoragePreference.setKey(PREFERENCE_KEY_BASE + mUser.id);
123             if (mSize != SIZE_NOT_SET) {
124                 mStoragePreference.setStorageSize(mSize, mTotalSizeBytes);
125             }
126 
127             mPreferenceGroup.setVisible(mIsVisible);
128             mPreferenceGroup.addPreference(mStoragePreference);
129             maybeSetIcon();
130         }
131     }
132 
133     @Override
isAvailable()134     public boolean isAvailable() {
135         return true;
136     }
137 
138     @Override
getPreferenceKey()139     public String getPreferenceKey() {
140         return mStoragePreference != null ? mStoragePreference.getKey() : null;
141     }
142 
143     /**
144      * Returns the user for which this is the secondary user controller.
145      */
146     @NonNull
getUser()147     public UserInfo getUser() {
148         return mUser;
149     }
150 
151     /**
152      * Sets the size for the preference.
153      *
154      * @param size Size in bytes.
155      */
setSize(long size)156     public void setSize(long size) {
157         mSize = size;
158         if (mStoragePreference != null) {
159             mStoragePreference.setStorageSize(mSize, mTotalSizeBytes);
160         }
161     }
162 
163     /**
164      * Sets the total size for the preference for the progress bar.
165      *
166      * @param totalSizeBytes Total size in bytes.
167      */
setTotalSize(long totalSizeBytes)168     public void setTotalSize(long totalSizeBytes) {
169         mTotalSizeBytes = totalSizeBytes;
170     }
171 
172     /**
173      * Sets visibility of the PreferenceGroup of secondary user.
174      *
175      * @param visible Visibility of the PreferenceGroup.
176      */
setPreferenceGroupVisible(boolean visible)177     public void setPreferenceGroupVisible(boolean visible) {
178         mIsVisible = visible;
179         if (mPreferenceGroup != null) {
180             mPreferenceGroup.setVisible(mIsVisible);
181         }
182     }
183 
184     @Override
handleResult(SparseArray<StorageAsyncLoader.StorageResult> stats)185     public void handleResult(SparseArray<StorageAsyncLoader.StorageResult> stats) {
186         final StorageAsyncLoader.StorageResult result = stats.get(getUser().id);
187         if (result != null) {
188             setSize(result.externalStats.totalBytes);
189         }
190     }
191 
192     @Override
handleUserIcons(SparseArray<Drawable> fetchedIcons)193     public void handleUserIcons(SparseArray<Drawable> fetchedIcons) {
194         mUserIcon = fetchedIcons.get(mUser.id);
195         maybeSetIcon();
196     }
197 
maybeSetIcon()198     private void maybeSetIcon() {
199         if (mUserIcon != null && mStoragePreference != null) {
200             mStoragePreference.setIcon(mUserIcon);
201         }
202     }
203 
204     @VisibleForTesting
205     static class NoSecondaryUserController extends AbstractPreferenceController implements
206             PreferenceControllerMixin {
NoSecondaryUserController(Context context)207         public NoSecondaryUserController(Context context) {
208             super(context);
209         }
210 
211         @Override
displayPreference(PreferenceScreen screen)212         public void displayPreference(PreferenceScreen screen) {
213             final PreferenceGroup group = screen.findPreference(TARGET_PREFERENCE_GROUP_KEY);
214             if (group == null) {
215                 return;
216             }
217             screen.removePreference(group);
218         }
219 
220         @Override
isAvailable()221         public boolean isAvailable() {
222             return true;
223         }
224 
225         @Override
getPreferenceKey()226         public String getPreferenceKey() {
227             return null;
228         }
229     }
230 }
231