import android.provider.ContactsContract.Profile;
import android.provider.ContactsContract.RawContacts;
import android.provider.Settings;
-import android.service.persistentdata.PersistentDataBlockManager;
import android.support.annotation.StringRes;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceGroup;
package com.android.settings.applications;
import android.content.pm.UserInfo;
+
import java.util.List;
/**
import android.content.Context;
import android.content.Intent;
import android.content.Loader;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
import com.android.settings.deviceinfo.storage.StorageAsyncLoader;
import com.android.settings.deviceinfo.storage.StorageItemPreferenceController;
import com.android.settings.deviceinfo.storage.StorageSummaryDonutPreferenceController;
+import com.android.settings.deviceinfo.storage.UserIconLoader;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settingslib.applications.StorageStatsSource;
implements LoaderManager.LoaderCallbacks<SparseArray<StorageAsyncLoader.AppsStorageResult>> {
private static final String TAG = "StorageDashboardFrag";
private static final int STORAGE_JOB_ID = 0;
+ private static final int ICON_JOB_ID = 1;
private static final int OPTIONS_MENU_MIGRATE_DATA = 100;
private VolumeInfo mVolume;
private List<PreferenceController> mSecondaryUsers;
@Override
- public void onResume() {
- super.onResume();
- getLoaderManager().initLoader(STORAGE_JOB_ID, Bundle.EMPTY, this);
- }
-
- @Override
- public Loader<SparseArray<StorageAsyncLoader.AppsStorageResult>> onCreateLoader(int id,
- Bundle args) {
- Context context = getContext();
- return new StorageAsyncLoader(context,
- new UserManagerWrapperImpl(context.getSystemService(UserManager.class)),
- mVolume.fsUuid,
- new StorageStatsSource(context),
- new PackageManagerWrapperImpl(context.getPackageManager()));
- }
-
- @Override
- public void onLoadFinished(Loader<SparseArray<StorageAsyncLoader.AppsStorageResult>> loader,
- SparseArray<StorageAsyncLoader.AppsStorageResult> data) {
- mPreferenceController.onLoadFinished(data.get(UserHandle.myUserId()));
- updateSecondaryUserControllers(mSecondaryUsers, data);
- }
-
- @Override
- public void onLoaderReset(Loader<SparseArray<StorageAsyncLoader.AppsStorageResult>> loader) {
- }
-
- @Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
}
@Override
+ public void onResume() {
+ super.onResume();
+ getLoaderManager().initLoader(STORAGE_JOB_ID, Bundle.EMPTY, this);
+ getLoaderManager().initLoader(ICON_JOB_ID, Bundle.EMPTY, new IconLoaderCallbacks());
+ }
+
+ @Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.SETTINGS_STORAGE_CATEGORY;
}
}
};
+
+ @Override
+ public Loader<SparseArray<StorageAsyncLoader.AppsStorageResult>> onCreateLoader(int id,
+ Bundle args) {
+ Context context = getContext();
+ return new StorageAsyncLoader(context,
+ new UserManagerWrapperImpl(context.getSystemService(UserManager.class)),
+ mVolume.fsUuid,
+ new StorageStatsSource(context),
+ new PackageManagerWrapperImpl(context.getPackageManager()));
+ }
+
+ @Override
+ public void onLoadFinished(Loader<SparseArray<StorageAsyncLoader.AppsStorageResult>> loader,
+ SparseArray<StorageAsyncLoader.AppsStorageResult> data) {
+ mPreferenceController.onLoadFinished(data.get(UserHandle.myUserId()));
+ updateSecondaryUserControllers(mSecondaryUsers, data);
+ }
+
+ @Override
+ public void onLoaderReset(Loader<SparseArray<StorageAsyncLoader.AppsStorageResult>> loader) {
+ }
+
+ /**
+ * IconLoaderCallbacks exists because StorageDashboardFragment already implements
+ * LoaderCallbacks for a different type.
+ */
+ public final class IconLoaderCallbacks
+ implements LoaderManager.LoaderCallbacks<SparseArray<Drawable>> {
+ @Override
+ public Loader<SparseArray<Drawable>> onCreateLoader(int id, Bundle args) {
+ return new UserIconLoader(
+ getContext(),
+ () -> UserIconLoader.loadUserIconsWithContext(getContext()));
+ }
+
+ @Override
+ public void onLoadFinished(
+ Loader<SparseArray<Drawable>> loader, SparseArray<Drawable> data) {
+ mSecondaryUsers
+ .stream()
+ .filter(controller -> controller instanceof UserIconLoader.UserIconHandler)
+ .forEach(
+ controller ->
+ ((UserIconLoader.UserIconHandler) controller)
+ .handleUserIcons(data));
+ }
+
+ @Override
+ public void onLoaderReset(Loader<SparseArray<Drawable>> loader) {}
+ }
}
import android.content.Context;
import android.content.pm.UserInfo;
+import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
* SecondaryUserController controls the preferences on the Storage screen which had to do with
* secondary users.
*/
-public class SecondaryUserController extends PreferenceController implements
- StorageAsyncLoader.ResultHandler {
+public class SecondaryUserController extends PreferenceController
+ implements StorageAsyncLoader.ResultHandler, UserIconLoader.UserIconHandler {
// PreferenceGroupKey to try to add our preference onto.
private static final String TARGET_PREFERENCE_GROUP_KEY = "pref_secondary_users";
private static final String PREFERENCE_KEY_BASE = "pref_user_";
}
if (info == null || Utils.isProfileOf(primaryUser, info)) {
- controllers.add(new UserProfileController(context, info,
- USER_PROFILE_INSERTION_LOCATION));
+ controllers.add(
+ new UserProfileController(
+ context, info, userManager, USER_PROFILE_INSERTION_LOCATION));
continue;
}
mStoragePreference.setStorageSize(mSize, mTotalSizeBytes);
}
- // TODO(b/36252572): Set the user icon appropriately here.
-
group.setVisible(true);
group.addPreference(mStoragePreference);
}
}
}
+ @Override
+ public void handleUserIcons(SparseArray<Drawable> fetchedIcons) {
+ Drawable userIcon = fetchedIcons.get(mUser.id);
+ if (userIcon != null) {
+ mStoragePreference.setIcon(userIcon);
+ }
+ }
+
private static class NoSecondaryUserController extends PreferenceController {
public NoSecondaryUserController(Context context) {
super(context);
--- /dev/null
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.deviceinfo.storage;
+
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.graphics.drawable.Drawable;
+import android.os.UserManager;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.internal.util.Preconditions;
+import com.android.settings.Utils;
+import com.android.settings.utils.AsyncLoader;
+
+/**
+ * Fetches a user icon as a loader using a given icon loading lambda.
+ */
+public class UserIconLoader extends AsyncLoader<SparseArray<Drawable>> {
+ private FetchUserIconTask mTask;
+
+ /**
+ * Task to load all user icons.
+ */
+ public interface FetchUserIconTask {
+ SparseArray<Drawable> getUserIcons();
+ }
+
+ /**
+ * Handle the output of this task.
+ */
+ public interface UserIconHandler {
+ void handleUserIcons(SparseArray<Drawable> fetchedIcons);
+ }
+
+ public UserIconLoader(Context context, FetchUserIconTask task) {
+ super(context);
+ mTask = Preconditions.checkNotNull(task);
+ }
+
+ @Override
+ public SparseArray<Drawable> loadInBackground() {
+ return mTask.getUserIcons();
+ }
+
+ @Override
+ protected void onDiscardResult(SparseArray<Drawable> result) {}
+
+ /**
+ * Loads the user icons using a given context. This returns a {@link SparseArray} which maps
+ * user ids to their user icons.
+ */
+ public static SparseArray<Drawable> loadUserIconsWithContext(Context context) {
+ SparseArray<Drawable> value = new SparseArray<>();
+ UserManager um = context.getSystemService(UserManager.class);
+ for (UserInfo userInfo : um.getUsers()) {
+ value.put(userInfo.id, Utils.getUserIcon(context, um, userInfo));
+ }
+ return value;
+ }
+}
import android.content.Context;
import android.content.Intent;
import android.content.pm.UserInfo;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.storage.VolumeInfo;
import android.support.v7.preference.Preference;
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.util.Preconditions;
import com.android.settings.Utils;
+import com.android.settings.applications.UserManagerWrapper;
import com.android.settings.core.PreferenceController;
import com.android.settings.deviceinfo.StorageItemPreference;
import com.android.settings.deviceinfo.StorageProfileFragment;
import com.android.settingslib.drawer.SettingsDrawerActivity;
-/**
- * Defines a {@link PreferenceController} which handles a single profile of the primary user.
- */
-public class UserProfileController extends PreferenceController implements
- StorageAsyncLoader.ResultHandler {
+/** Defines a {@link PreferenceController} which handles a single profile of the primary user. */
+public class UserProfileController extends PreferenceController
+ implements StorageAsyncLoader.ResultHandler, UserIconLoader.UserIconHandler {
private static final String PREFERENCE_KEY_BASE = "pref_profile_";
private StorageItemPreference mStoragePreference;
+ private UserManagerWrapper mUserManager;
private UserInfo mUser;
private long mTotalSizeBytes;
private final int mPreferenceOrder;
- public UserProfileController(Context context, UserInfo info, int preferenceOrder) {
+ public UserProfileController(
+ Context context, UserInfo info, UserManagerWrapper userManager, int preferenceOrder) {
super(context);
mUser = Preconditions.checkNotNull(info);
+ mUserManager = userManager;
mPreferenceOrder = preferenceOrder;
}
mStoragePreference.setOrder(mPreferenceOrder);
mStoragePreference.setKey(PREFERENCE_KEY_BASE + mUser.id);
mStoragePreference.setTitle(mUser.name);
- // TODO(b/36252572): Set user icon here.
screen.addPreference(mStoragePreference);
}
public void setTotalSize(long totalSize) {
mTotalSizeBytes = totalSize;
}
+
+ @Override
+ public void handleUserIcons(SparseArray<Drawable> fetchedIcons) {
+ Drawable userIcon = fetchedIcons.get(mUser.id);
+ if (userIcon != null) {
+ mStoragePreference.setIcon(userIcon);
+ }
+ }
}
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.pm.UserInfo;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.Drawable;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceScreen;
import com.android.settings.TestConfig;
import com.android.settings.applications.UserManagerWrapper;
import com.android.settings.core.PreferenceController;
+import com.android.settingslib.R;
import com.android.settingslib.applications.StorageStatsSource;
+import com.android.settingslib.drawable.UserIconDrawable;
import org.junit.Before;
import org.junit.Test;
// We should have the NoSecondaryUserController.
assertThat(controllers.get(0) instanceof SecondaryUserController).isFalse();
}
+
+ @Test
+ public void iconCallbackChangesPreferenceIcon() throws Exception {
+ SparseArray<Drawable> icons = new SparseArray<>();
+ Bitmap userBitmap =
+ BitmapFactory.decodeResource(
+ RuntimeEnvironment.application.getResources(), R.drawable.home);
+ UserIconDrawable drawable = new UserIconDrawable(100 /* size */).setIcon(userBitmap).bake();
+ icons.put(10, drawable);
+ mPrimaryUser.name = TEST_NAME;
+ mPrimaryUser.id = 10;
+ mController.displayPreference(mScreen);
+
+ mController.handleUserIcons(icons);
+
+ final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
+ verify(mGroup).addPreference(argumentCaptor.capture());
+ Preference preference = argumentCaptor.getValue();
+ assertThat(preference.getIcon()).isEqualTo(drawable);
+ }
}
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.Intent;
import android.content.pm.UserInfo;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.Drawable;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import android.util.SparseArray;
import com.android.settings.TestConfig;
import com.android.settings.applications.UserManagerWrapper;
import com.android.settings.deviceinfo.StorageProfileFragment;
+import com.android.settingslib.R;
import com.android.settingslib.applications.StorageStatsSource;
+import com.android.settingslib.drawable.UserIconDrawable;
import org.junit.Before;
import org.junit.Test;
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
mPrimaryProfile = new UserInfo();
- mController = new UserProfileController(mContext, mPrimaryProfile, 0);
+ mController = new UserProfileController(mContext, mPrimaryProfile, mUserManager, 0);
when(mScreen.getContext()).thenReturn(mContext);
- }
-
- @Test
- public void controllerAddsPrimaryProfilePreference() throws Exception {
mPrimaryProfile.name = TEST_NAME;
mPrimaryProfile.id = 10;
mController.displayPreference(mScreen);
+ }
+ @Test
+ public void controllerAddsPrimaryProfilePreference() throws Exception {
final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
verify(mScreen).addPreference(argumentCaptor.capture());
Preference preference = argumentCaptor.getValue();
@Test
public void tappingProfilePreferenceSendsToStorageProfileFragment() throws Exception {
- mPrimaryProfile.name = TEST_NAME;
- mPrimaryProfile.id = 10;
- mController.displayPreference(mScreen);
final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
verify(mScreen).addPreference(argumentCaptor.capture());
@Test
public void acceptingResultUpdatesPreferenceSize() throws Exception {
- mPrimaryProfile.name = TEST_NAME;
- mPrimaryProfile.id = 10;
- mController.displayPreference(mScreen);
SparseArray<StorageAsyncLoader.AppsStorageResult> result = new SparseArray<>();
StorageAsyncLoader.AppsStorageResult userResult =
new StorageAsyncLoader.AppsStorageResult();
assertThat(preference.getSummary()).isEqualTo("99.00B");
}
+
+ @Test
+ public void iconCallbackChangesPreferenceIcon() throws Exception {
+ SparseArray<Drawable> icons = new SparseArray<>();
+ Bitmap userBitmap =
+ BitmapFactory.decodeResource(
+ RuntimeEnvironment.application.getResources(), R.drawable.home);
+ UserIconDrawable drawable = new UserIconDrawable(100 /* size */).setIcon(userBitmap).bake();
+ icons.put(10, drawable);
+
+ mController.handleUserIcons(icons);
+
+ final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
+ verify(mScreen).addPreference(argumentCaptor.capture());
+ Preference preference = argumentCaptor.getValue();
+ assertThat(preference.getIcon()).isEqualTo(drawable);
+ }
}
\ No newline at end of file