Merge "Add user icon to the other user preferences." into oc-dev
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 4c8fb2d..d04ae8d 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -73,7 +73,6 @@
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;
diff --git a/src/com/android/settings/applications/UserManagerWrapper.java b/src/com/android/settings/applications/UserManagerWrapper.java
index daefb84..5b4ed2a 100644
--- a/src/com/android/settings/applications/UserManagerWrapper.java
+++ b/src/com/android/settings/applications/UserManagerWrapper.java
@@ -17,6 +17,7 @@
package com.android.settings.applications;
import android.content.pm.UserInfo;
+
import java.util.List;
/**
diff --git a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
index 75c0e75..602e65f 100644
--- a/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
+++ b/src/com/android/settings/deviceinfo/StorageDashboardFragment.java
@@ -20,6 +20,7 @@
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;
@@ -47,6 +48,7 @@
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;
@@ -61,6 +63,7 @@
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;
@@ -71,34 +74,6 @@
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);
@@ -140,6 +115,13 @@
}
@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;
}
@@ -227,4 +209,55 @@
}
};
+
+ @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) {}
+ }
}
diff --git a/src/com/android/settings/deviceinfo/storage/SecondaryUserController.java b/src/com/android/settings/deviceinfo/storage/SecondaryUserController.java
index b3e89c6..62e946d 100644
--- a/src/com/android/settings/deviceinfo/storage/SecondaryUserController.java
+++ b/src/com/android/settings/deviceinfo/storage/SecondaryUserController.java
@@ -18,6 +18,7 @@
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;
@@ -37,8 +38,8 @@
* 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_";
@@ -69,8 +70,9 @@
}
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;
}
@@ -109,8 +111,6 @@
mStoragePreference.setStorageSize(mSize, mTotalSizeBytes);
}
- // TODO(b/36252572): Set the user icon appropriately here.
-
group.setVisible(true);
group.addPreference(mStoragePreference);
}
@@ -161,6 +161,14 @@
}
}
+ @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);
diff --git a/src/com/android/settings/deviceinfo/storage/UserIconLoader.java b/src/com/android/settings/deviceinfo/storage/UserIconLoader.java
new file mode 100644
index 0000000..4f00c3c
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/storage/UserIconLoader.java
@@ -0,0 +1,75 @@
+/*
+ * 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;
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/storage/UserProfileController.java b/src/com/android/settings/deviceinfo/storage/UserProfileController.java
index 0e19740..18fa7b7 100644
--- a/src/com/android/settings/deviceinfo/storage/UserProfileController.java
+++ b/src/com/android/settings/deviceinfo/storage/UserProfileController.java
@@ -19,6 +19,7 @@
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;
@@ -28,25 +29,27 @@
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;
}
@@ -66,7 +69,6 @@
mStoragePreference.setOrder(mPreferenceOrder);
mStoragePreference.setKey(PREFERENCE_KEY_BASE + mUser.id);
mStoragePreference.setTitle(mUser.name);
- // TODO(b/36252572): Set user icon here.
screen.addPreference(mStoragePreference);
}
@@ -110,4 +112,12 @@
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);
+ }
+ }
}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/storage/SecondaryUserControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/storage/SecondaryUserControllerTest.java
index 16bf1ae..c55ba36 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/storage/SecondaryUserControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/storage/SecondaryUserControllerTest.java
@@ -19,12 +19,14 @@
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;
@@ -34,7 +36,9 @@
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;
@@ -187,4 +191,24 @@
// 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);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/storage/UserProfileControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/storage/UserProfileControllerTest.java
index ed49da4..0c3fc47 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/storage/UserProfileControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/storage/UserProfileControllerTest.java
@@ -18,7 +18,6 @@
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;
@@ -26,6 +25,9 @@
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;
@@ -36,7 +38,9 @@
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;
@@ -66,16 +70,15 @@
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);
+ mPrimaryProfile.name = TEST_NAME;
+ mPrimaryProfile.id = 10;
+ mController.displayPreference(mScreen);
}
@Test
public void controllerAddsPrimaryProfilePreference() 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());
Preference preference = argumentCaptor.getValue();
@@ -86,9 +89,6 @@
@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());
@@ -105,9 +105,6 @@
@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();
@@ -121,4 +118,21 @@
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