Add support for user profiles to the Storage Settings.

This adds new preferences for each profile (such as the work
profile) and defines a new view for viewing the storage
breakdown for the individual profile. The functionality closely
mimics the presentation on the main view, but without the system-wide
breakdown and without any additional users/profiles.

Bug: 34715777
Test: Settings Robotests

Change-Id: I19d449b648c6566331fd02e45c2e45f8c74ea7e7
This commit is contained in:
Daniel Nishi
2017-02-15 15:25:48 -08:00
parent 182e6ce2c7
commit 9f60f42a94
15 changed files with 553 additions and 62 deletions

View File

@@ -1,13 +1,25 @@
package com.android.settings;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.storage.DiskInfo;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.text.format.DateUtils;
import java.net.InetAddress;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -16,9 +28,7 @@ import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import java.net.InetAddress;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
@@ -97,4 +107,13 @@ public class UtilsTest {
assertThat(Utils.formatElapsedTime(mContext, testMillis, false)).isEqualTo(expectedTime);
}
@Test
public void testInitializeVolumeDoesntBreakOnNullVolume() {
VolumeInfo info = new VolumeInfo("id", 0, new DiskInfo("id", 0), "");
StorageManager storageManager = mock(StorageManager.class, RETURNS_DEEP_STUBS);
when(storageManager.findVolumeById(anyString())).thenReturn(info);
Utils.maybeInitializeVolume(storageManager, new Bundle());
}
}

View File

@@ -79,11 +79,4 @@ public class StorageDashboardFragmentTest {
assertThat(indexRes).isNotNull();
assertThat(indexRes.get(0).xmlResId).isEqualTo(mFragment.getPreferenceScreenResId());
}
@Test
public void testInitializeVolumeDoesntBreakOnNullVolume() {
VolumeInfo info = new VolumeInfo("id", 0, new DiskInfo("id", 0), "");
when(mStorageManager.findVolumeById(anyString())).thenReturn(info);
mFragment.initializeVolume(mStorageManager, new Bundle());
}
}

View File

@@ -28,11 +28,13 @@ import android.content.pm.UserInfo;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceScreen;
import android.util.SparseArray;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.applications.UserManagerWrapper;
import com.android.settings.core.PreferenceController;
import com.android.settingslib.applications.StorageStatsSource;
import org.junit.Before;
import org.junit.Test;
@@ -130,7 +132,7 @@ public class SecondaryUserControllerTest {
}
@Test
public void profilesOfPrimaryUserAreIgnored() throws Exception {
public void profilesOfPrimaryUserAreNotIgnored() throws Exception {
ArrayList<UserInfo> userInfos = new ArrayList<>();
UserInfo secondaryUser = new UserInfo();
secondaryUser.id = mPrimaryUser.id;
@@ -142,7 +144,31 @@ public class SecondaryUserControllerTest {
List<PreferenceController> controllers =
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager);
assertThat(controllers).hasSize(1);
assertThat(controllers.get(0) instanceof SecondaryUserController).isFalse();
assertThat(controllers).hasSize(2);
assertThat(controllers.get(0) instanceof UserProfileController).isTrue();
assertThat(controllers.get(1) instanceof SecondaryUserController).isFalse();
}
@Test
public void controllerUpdatesPreferenceOnAcceptingResult() throws Exception {
mPrimaryUser.name = TEST_NAME;
mPrimaryUser.id = 10;
PreferenceScreen screen = mock(PreferenceScreen.class);
PreferenceGroup group = mock(PreferenceGroup.class);
when(screen.findPreference(anyString())).thenReturn(group);
when(group.getKey()).thenReturn(TARGET_PREFERENCE_GROUP_KEY);
mController.displayPreference(screen);
StorageAsyncLoader.AppsStorageResult userResult =
new StorageAsyncLoader.AppsStorageResult();
SparseArray<StorageAsyncLoader.AppsStorageResult> result = new SparseArray<>();
userResult.externalStats = new StorageStatsSource.ExternalStorageStats(99, 33, 33, 33);
result.put(10, userResult);
mController.handleResult(result);
final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
verify(group).addPreference(argumentCaptor.capture());
Preference preference = argumentCaptor.getValue();
assertThat(preference.getSummary()).isEqualTo("99.00B");
}
}

View File

@@ -0,0 +1,123 @@
/*
* 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 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 android.content.Context;
import android.content.Intent;
import android.content.pm.UserInfo;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import android.util.SparseArray;
import com.android.settings.SettingsActivity;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.SubSettings;
import com.android.settings.TestConfig;
import com.android.settings.applications.UserManagerWrapper;
import com.android.settings.deviceinfo.StorageProfileFragment;
import com.android.settingslib.applications.StorageStatsSource;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class UserProfileControllerTest {
private static final String TEST_NAME = "Fred";
@Mock
private UserManagerWrapper mUserManager;
private Context mContext;
private UserProfileController mController;
private UserInfo mPrimaryProfile;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
mPrimaryProfile = new UserInfo();
mController = new UserProfileController(mContext, mPrimaryProfile, 0);
}
@Test
public void controllerAddsPrimaryProfilePreference() throws Exception {
mPrimaryProfile.name = TEST_NAME;
mPrimaryProfile.id = 10;
PreferenceScreen screen = mock(PreferenceScreen.class);
mController.displayPreference(screen);
final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
verify(screen).addPreference(argumentCaptor.capture());
Preference preference = argumentCaptor.getValue();
assertThat(preference.getTitle()).isEqualTo(TEST_NAME);
assertThat(preference.getKey()).isEqualTo("pref_profile_10");
}
@Test
public void tappingProfilePreferenceSendsToStorageProfileFragment() throws Exception {
mPrimaryProfile.name = TEST_NAME;
mPrimaryProfile.id = 10;
PreferenceScreen screen = mock(PreferenceScreen.class);
mController.displayPreference(screen);
final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
verify(screen).addPreference(argumentCaptor.capture());
Preference preference = argumentCaptor.getValue();
assertThat(mController.handlePreferenceTreeClick(preference)).isTrue();
final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mContext).startActivity(intentCaptor.capture());
Intent intent = intentCaptor.getValue();
assertThat(intent.getComponent().getClassName()).isEqualTo(SubSettings.class.getName());
assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT)).isEqualTo(
StorageProfileFragment.class.getName());
}
@Test
public void acceptingResultUpdatesPreferenceSize() throws Exception {
mPrimaryProfile.name = TEST_NAME;
mPrimaryProfile.id = 10;
PreferenceScreen screen = mock(PreferenceScreen.class);
mController.displayPreference(screen);
SparseArray<StorageAsyncLoader.AppsStorageResult> result = new SparseArray<>();
StorageAsyncLoader.AppsStorageResult userResult =
new StorageAsyncLoader.AppsStorageResult();
userResult.externalStats = new StorageStatsSource.ExternalStorageStats(99, 33, 33, 33);
result.put(10, userResult);
mController.handleResult(result);
final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
verify(screen).addPreference(argumentCaptor.capture());
Preference preference = argumentCaptor.getValue();
assertThat(preference.getSummary()).isEqualTo("99.00B");
}
}