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.app.ActivityManager; 20 import android.content.Context; 21 import android.content.pm.UserInfo; 22 import android.graphics.drawable.Drawable; 23 import android.os.UserManager; 24 import android.util.SparseArray; 25 26 import androidx.annotation.NonNull; 27 import androidx.annotation.Nullable; 28 import androidx.annotation.VisibleForTesting; 29 import androidx.preference.PreferenceGroup; 30 import androidx.preference.PreferenceScreen; 31 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 * NonCurrentUserController controls the preferences on the Storage screen which had to do with 41 * other users. 42 */ 43 public class NonCurrentUserController 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_non_current_users"; 48 private static final String PREFERENCE_KEY_BASE = "pref_user_"; 49 private static final int SIZE_NOT_SET = -1; 50 51 private @NonNull 52 UserInfo mUser; 53 private @Nullable 54 StorageItemPreference mStoragePreference; 55 private PreferenceGroup mPreferenceGroup; 56 private Drawable mUserIcon; 57 private long mSize; 58 private long mTotalSizeBytes; 59 private boolean mIsVisible; 60 private int[] mProfiles; 61 private StorageCacheHelper mStorageCacheHelper; 62 63 /** 64 * Adds the appropriate controllers to a controller list for handling all full non current 65 * users on a device. 66 * 67 * @param context Context for initializing the preference controllers. 68 * @param userManager UserManagerWrapper for figuring out which controllers to add. 69 */ getNonCurrentUserControllers( Context context, UserManager userManager)70 public static List<NonCurrentUserController> getNonCurrentUserControllers( 71 Context context, UserManager userManager) { 72 int currentUserId = ActivityManager.getCurrentUser(); 73 List<NonCurrentUserController> controllers = new ArrayList<>(); 74 List<UserInfo> infos = userManager.getUsers(); 75 for (UserInfo info : infos) { 76 if (info.id == currentUserId || !info.isFull()) { 77 continue; 78 } 79 int[] profiles = userManager.getProfileIds(info.id, false /* enabledOnly */); 80 controllers.add(new NonCurrentUserController(context, info, profiles)); 81 } 82 return controllers; 83 } 84 85 /** 86 * Constructor for a given non-current user. 87 * 88 * @param context Context to initialize the underlying {@link AbstractPreferenceController}. 89 * @param info {@link UserInfo} for the non-current user which these controllers cover. 90 * @param profiles list of IDs or user and its profiles 91 */ 92 @VisibleForTesting NonCurrentUserController(Context context, @NonNull UserInfo info, @NonNull int[] profiles)93 NonCurrentUserController(Context context, @NonNull UserInfo info, @NonNull int[] profiles) { 94 super(context); 95 mUser = info; 96 mSize = SIZE_NOT_SET; 97 mStorageCacheHelper = new StorageCacheHelper(context, info.id); 98 mProfiles = profiles; 99 } 100 101 /** 102 * Constructor for a given non-current user. 103 * 104 * @param context Context to initialize the underlying {@link AbstractPreferenceController}. 105 * @param info {@link UserInfo} for the non-current user which these controllers cover. 106 */ 107 @VisibleForTesting NonCurrentUserController(Context context, @NonNull UserInfo info)108 NonCurrentUserController(Context context, @NonNull UserInfo info) { 109 super(context); 110 mUser = info; 111 mSize = SIZE_NOT_SET; 112 mStorageCacheHelper = new StorageCacheHelper(context, info.id); 113 mProfiles = new int[]{info.id}; 114 } 115 116 @Override displayPreference(PreferenceScreen screen)117 public void displayPreference(PreferenceScreen screen) { 118 if (mStoragePreference == null) { 119 mStoragePreference = new StorageItemPreference(screen.getContext()); 120 121 mPreferenceGroup = screen.findPreference(TARGET_PREFERENCE_GROUP_KEY); 122 mStoragePreference.setTitle(mUser.name); 123 mStoragePreference.setKey(PREFERENCE_KEY_BASE + mUser.id); 124 setSize(mStorageCacheHelper.retrieveUsedSize(), false /* animate */); 125 126 mPreferenceGroup.setVisible(mIsVisible); 127 mPreferenceGroup.addPreference(mStoragePreference); 128 maybeSetIcon(); 129 } 130 } 131 132 @Override isAvailable()133 public boolean isAvailable() { 134 return true; 135 } 136 137 @Override getPreferenceKey()138 public String getPreferenceKey() { 139 return mStoragePreference != null ? mStoragePreference.getKey() : null; 140 } 141 142 /** 143 * Returns the user for which this is the non-current user controller. 144 */ 145 @NonNull getUser()146 public UserInfo getUser() { 147 return mUser; 148 } 149 150 /** 151 * Sets the size for the preference. 152 * 153 * @param size Size in bytes. 154 */ setSize(long size, boolean animate)155 public void setSize(long size, boolean animate) { 156 mSize = size; 157 if (mStoragePreference != null) { 158 mStoragePreference.setStorageSize(mSize, mTotalSizeBytes, animate); 159 } 160 } 161 162 /** 163 * Sets the total size for the preference for the progress bar. 164 * 165 * @param totalSizeBytes Total size in bytes. 166 */ setTotalSize(long totalSizeBytes)167 public void setTotalSize(long totalSizeBytes) { 168 mTotalSizeBytes = totalSizeBytes; 169 } 170 171 /** 172 * Sets visibility of the PreferenceGroup of non-current user. 173 * 174 * @param visible Visibility of the PreferenceGroup. 175 */ setPreferenceGroupVisible(boolean visible)176 public void setPreferenceGroupVisible(boolean visible) { 177 mIsVisible = visible; 178 if (mPreferenceGroup != null) { 179 mPreferenceGroup.setVisible(mIsVisible); 180 } 181 } 182 183 @Override handleResult(SparseArray<StorageAsyncLoader.StorageResult> stats)184 public void handleResult(SparseArray<StorageAsyncLoader.StorageResult> stats) { 185 if (stats == null) { 186 setSize(mStorageCacheHelper.retrieveUsedSize(), false /* animate */); 187 return; 188 } 189 final StorageAsyncLoader.StorageResult result = stats.get(getUser().id); 190 191 if (result != null) { 192 long totalSize = 0; 193 for (int id : mProfiles) { 194 totalSize += stats.get(id).externalStats.totalBytes; 195 } 196 setSize(totalSize, true /* animate */); 197 // TODO(b/171758224): Update the source of size info 198 mStorageCacheHelper.cacheUsedSize(totalSize); 199 } 200 } 201 202 @Override handleUserIcons(SparseArray<Drawable> fetchedIcons)203 public void handleUserIcons(SparseArray<Drawable> fetchedIcons) { 204 mUserIcon = fetchedIcons.get(mUser.id); 205 maybeSetIcon(); 206 } 207 maybeSetIcon()208 private void maybeSetIcon() { 209 if (mUserIcon != null && mStoragePreference != null) { 210 mStoragePreference.setIcon(mUserIcon); 211 } 212 } 213 } 214