Implements profile selection tab in Storage Settings

- StorageDashboardFragment and StorageItemPreferenceController works only
  for one profile per instance.
- StorageAsyncLoader loads for all users(profiles) and regards each user independent.
- SecondaryUserController will not load personal profile user in work profile tab.
- Cleanup some unused profile related files.

Bug: 174964885
Test: atest com.android.settings.deviceinfo
      atest com.android.settings.deviceinfo.storage
      make RunSettingsRoboTests -j ROBOTEST_FILTER=com.android.settings.deviceinfo
      make RunSettingsRoboTests -j ROBOTEST_FILTER=com.android.settings.deviceinfo.storage
Change-Id: I8361c29bc240c519c7261b19522c41439479c1c2
This commit is contained in:
Arc Wang
2021-04-29 18:54:10 +08:00
parent 7307e04ef2
commit fa6e82b879
14 changed files with 214 additions and 640 deletions

View File

@@ -36,9 +36,7 @@ com.android.settings.datausage.DataUsageList
com.android.settings.datausage.DataUsageSummary
com.android.settings.datetime.timezone.TimeZoneSettings
com.android.settings.development.compat.PlatformCompatDashboard
com.android.settings.deviceinfo.PrivateVolumeSettings
com.android.settings.deviceinfo.PublicVolumeSettings
com.android.settings.deviceinfo.StorageProfileFragment
com.android.settings.deviceinfo.legal.ModuleLicensesDashboard
com.android.settings.enterprise.ApplicationListFragment$AdminGrantedPermissionCamera
com.android.settings.enterprise.ApplicationListFragment$AdminGrantedPermissionLocation

View File

@@ -22,6 +22,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -112,7 +113,8 @@ public class SecondaryUserControllerTest {
when(mUserManager.getPrimaryUser()).thenReturn(mPrimaryUser);
when(mUserManager.getUsers()).thenReturn(userInfos);
final List<AbstractPreferenceController> controllers =
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager);
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager,
false /* isWorkProfileOnly */);
assertThat(controllers).hasSize(1);
// We should have the NoSecondaryUserController.
@@ -122,15 +124,17 @@ public class SecondaryUserControllerTest {
@Test
public void getSecondaryUserControllers_notWorkProfile_addSecondaryUserController() {
final ArrayList<UserInfo> userInfos = new ArrayList<>();
final UserInfo secondaryUser = new UserInfo();
final UserInfo secondaryUser = spy(new UserInfo());
secondaryUser.id = 10;
secondaryUser.profileGroupId = 101010; // this just has to be something not 0
when(secondaryUser.isManagedProfile()).thenReturn(false);
userInfos.add(mPrimaryUser);
userInfos.add(secondaryUser);
when(mUserManager.getPrimaryUser()).thenReturn(mPrimaryUser);
when(mUserManager.getUsers()).thenReturn(userInfos);
final List<AbstractPreferenceController> controllers =
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager);
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager,
false /* isWorkProfileOnly */);
assertThat(controllers).hasSize(1);
assertThat(controllers.get(0) instanceof SecondaryUserController).isTrue();
@@ -139,20 +143,41 @@ public class SecondaryUserControllerTest {
@Test
public void getSecondaryUserControllers_workProfile_addNoSecondaryUserController() {
final ArrayList<UserInfo> userInfos = new ArrayList<>();
final UserInfo secondaryUser = new UserInfo();
final UserInfo secondaryUser = spy(new UserInfo());
secondaryUser.id = 10;
secondaryUser.profileGroupId = 101010; // this just has to be something not 0
when(secondaryUser.isManagedProfile()).thenReturn(true);
userInfos.add(mPrimaryUser);
userInfos.add(secondaryUser);
when(mUserManager.getPrimaryUser()).thenReturn(mPrimaryUser);
when(mUserManager.getUsers()).thenReturn(userInfos);
final List<AbstractPreferenceController> controllers =
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager);
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager,
false /* isWorkProfileOnly */);
assertThat(controllers).hasSize(1);
assertThat(controllers.get(0) instanceof SecondaryUserController).isTrue();
}
@Test
public void getSecondaryUserControllers_notWorkProfileWorkProfileOnly_addNoSecondController() {
final ArrayList<UserInfo> userInfos = new ArrayList<>();
final UserInfo secondaryUser = spy(new UserInfo());
secondaryUser.id = 10;
secondaryUser.profileGroupId = 101010; // this just has to be something not 0
when(secondaryUser.isManagedProfile()).thenReturn(false);
userInfos.add(mPrimaryUser);
userInfos.add(secondaryUser);
when(mUserManager.getPrimaryUser()).thenReturn(mPrimaryUser);
when(mUserManager.getUsers()).thenReturn(userInfos);
final List<AbstractPreferenceController> controllers =
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager,
true /* isWorkProfileOnly */);
assertThat(controllers).hasSize(1);
assertThat(controllers.get(0) instanceof SecondaryUserController).isFalse();
}
@Test
public void profilesOfPrimaryUserAreIgnored() {
final ArrayList<UserInfo> userInfos = new ArrayList<>();
@@ -164,7 +189,8 @@ public class SecondaryUserControllerTest {
when(mUserManager.getUsers()).thenReturn(userInfos);
final List<AbstractPreferenceController> controllers =
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager);
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager,
false /* isWorkProfileOnly */);
assertThat(controllers).hasSize(1);
assertThat(controllers.get(0) instanceof SecondaryUserController).isFalse();
@@ -206,7 +232,8 @@ public class SecondaryUserControllerTest {
when(mUserManager.getPrimaryUser()).thenReturn(mPrimaryUser);
when(mUserManager.getUsers()).thenReturn(userInfos);
final List<AbstractPreferenceController> controllers =
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager);
SecondaryUserController.getSecondaryUserControllers(mContext, mUserManager,
false /* isWorkProfileOnly */);
assertThat(controllers).hasSize(1);
// We should have the NoSecondaryUserController.

View File

@@ -94,7 +94,8 @@ public class StorageItemPreferenceControllerTest {
mVolume = spy(new VolumeInfo("id", 0, null, "id"));
// Note: null is passed as the Lifecycle because we are handling it outside of the normal
// Settings fragment lifecycle for test purposes.
mController = new StorageItemPreferenceController(mContext, mFragment, mVolume, mSvp);
mController = new StorageItemPreferenceController(mContext, mFragment, mVolume, mSvp,
false /* isWorkProfile */);
mPreference = new StorageItemPreference(mContext);
// Inflate the preference and the widget.
@@ -165,7 +166,7 @@ public class StorageItemPreferenceControllerTest {
mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mContext).startActivity(argumentCaptor.capture());
verify(mContext).startActivityAsUser(argumentCaptor.capture(), nullable(UserHandle.class));
final Intent intent = argumentCaptor.getValue();
assertThat(intent.getAction()).isEqualTo(fakeBrowseAction);
@@ -176,11 +177,12 @@ public class StorageItemPreferenceControllerTest {
mPreference.setKey(StorageItemPreferenceController.IMAGES_KEY);
final Context mockContext = getMockContext();
mController = new StorageItemPreferenceController(mockContext, mFragment, mVolume,
mSvp);
mSvp, false /* isWorkProfile */);
mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mockContext).startActivity(argumentCaptor.capture());
verify(mockContext).startActivityAsUser(argumentCaptor.capture(),
nullable(UserHandle.class));
final Intent intent = argumentCaptor.getValue();
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_VIEW);
@@ -192,11 +194,12 @@ public class StorageItemPreferenceControllerTest {
mPreference.setKey(StorageItemPreferenceController.AUDIOS_KEY);
final Context mockContext = getMockContext();
mController = new StorageItemPreferenceController(mockContext, mFragment, mVolume,
mSvp);
mSvp, false /* isWorkProfile */);
mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mockContext).startActivity(argumentCaptor.capture());
verify(mockContext).startActivityAsUser(argumentCaptor.capture(),
nullable(UserHandle.class));
final Intent intent = argumentCaptor.getValue();
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_VIEW);
@@ -240,7 +243,8 @@ public class StorageItemPreferenceControllerTest {
@Test
public void launchAppsIntent_forWork_settingsIntent() {
mController = new StorageItemPreferenceController(mContext, mFragment, mVolume, mSvp, true);
mController = new FakeStorageItemPreferenceController(mContext, mFragment, mVolume, mSvp,
true /* isWorkProfile */);
mPreference.setKey(StorageItemPreferenceController.APPS_KEY);
mController.handlePreferenceTreeClick(mPreference);
@@ -270,11 +274,12 @@ public class StorageItemPreferenceControllerTest {
mPreference.setKey(StorageItemPreferenceController.DOCUMENTS_AND_OTHER_KEY);
final Context mockContext = getMockContext();
mController = new StorageItemPreferenceController(mockContext, mFragment, mVolume,
mSvp);
mSvp, false /* isWorkProfile */);
mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mockContext).startActivity(argumentCaptor.capture());
verify(mockContext).startActivityAsUser(argumentCaptor.capture(),
nullable(UserHandle.class));
Intent intent = argumentCaptor.getValue();
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_VIEW);
@@ -304,11 +309,12 @@ public class StorageItemPreferenceControllerTest {
mPreference.setKey(StorageItemPreferenceController.VIDEOS_KEY);
final Context mockContext = getMockContext();
mController = new StorageItemPreferenceController(mockContext, mFragment, mVolume,
mSvp);
mSvp, false /* isWorkProfile */);
mController.handlePreferenceTreeClick(mPreference);
final ArgumentCaptor<Intent> argumentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mockContext).startActivity(argumentCaptor.capture());
verify(mockContext).startActivityAsUser(argumentCaptor.capture(),
nullable(UserHandle.class));
Intent intent = argumentCaptor.getValue();
assertThat(intent.getAction()).isEqualTo(Intent.ACTION_VIEW);
@@ -468,4 +474,20 @@ public class StorageItemPreferenceControllerTest {
when(resources.getString(anyInt())).thenReturn("");
return context;
}
private static class FakeStorageItemPreferenceController
extends StorageItemPreferenceController {
private static final int CURRENT_USER_ID = 10;
FakeStorageItemPreferenceController(Context context, Fragment hostFragment,
VolumeInfo volume, StorageVolumeProvider svp, boolean isWorkProfile) {
super(context, hostFragment, volume, svp, isWorkProfile);
}
@Override
int getCurrentUserId() {
return CURRENT_USER_ID;
}
}
}

View File

@@ -1,138 +0,0 @@
/*
* 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.android.settings.utils.FileSizeFormatter.MEGABYTE_IN_BYTES;
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.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.UserInfo;
import android.graphics.drawable.Drawable;
import android.util.SparseArray;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.SettingsActivity;
import com.android.settings.SubSettings;
import com.android.settings.deviceinfo.StorageProfileFragment;
import com.android.settingslib.applications.StorageStatsSource;
import com.android.settingslib.drawable.UserIconDrawable;
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.Robolectric;
import org.robolectric.RobolectricTestRunner;
@RunWith(RobolectricTestRunner.class)
public class UserProfileControllerTest {
private static final String TEST_NAME = "Fred";
@Mock
private PreferenceScreen mScreen;
private Context mContext;
private UserProfileController mController;
private UserInfo mPrimaryProfile;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mContext = spy(Robolectric.setupActivity(Activity.class));
mPrimaryProfile = new UserInfo();
mController = new UserProfileController(mContext, mPrimaryProfile, 0);
when(mScreen.getContext()).thenReturn(mContext);
mPrimaryProfile.name = TEST_NAME;
mPrimaryProfile.id = 10;
mController.displayPreference(mScreen);
}
@Test
public void controllerAddsPrimaryProfilePreference() {
final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
verify(mScreen).addPreference(argumentCaptor.capture());
final Preference preference = argumentCaptor.getValue();
assertThat(preference.getTitle()).isEqualTo(TEST_NAME);
assertThat(preference.getKey()).isEqualTo("pref_profile_10");
}
@Test
public void tappingProfilePreferenceSendsToStorageProfileFragment() {
final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
verify(mScreen).addPreference(argumentCaptor.capture());
final Preference preference = argumentCaptor.getValue();
assertThat(mController.handlePreferenceTreeClick(preference)).isTrue();
final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mContext).startActivity(intentCaptor.capture());
final 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() {
final SparseArray<StorageAsyncLoader.AppsStorageResult> result = new SparseArray<>();
final StorageAsyncLoader.AppsStorageResult userResult =
new StorageAsyncLoader.AppsStorageResult();
userResult.externalStats =
new StorageStatsSource.ExternalStorageStats(
99 * MEGABYTE_IN_BYTES,
33 * MEGABYTE_IN_BYTES,
33 * MEGABYTE_IN_BYTES,
33 * MEGABYTE_IN_BYTES, 0);
result.put(10, userResult);
mController.handleResult(result);
final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
verify(mScreen).addPreference(argumentCaptor.capture());
final Preference preference = argumentCaptor.getValue();
assertThat(preference.getSummary()).isEqualTo("0.10 GB");
}
@Test
public void iconCallbackChangesPreferenceIcon() {
final SparseArray<Drawable> icons = new SparseArray<>();
final UserIconDrawable drawable = mock(UserIconDrawable.class);
when(drawable.mutate()).thenReturn(drawable);
icons.put(mPrimaryProfile.id, drawable);
mController.handleUserIcons(icons);
final ArgumentCaptor<Preference> argumentCaptor = ArgumentCaptor.forClass(Preference.class);
verify(mScreen).addPreference(argumentCaptor.capture());
final Preference preference = argumentCaptor.getValue();
assertThat(preference.getIcon()).isEqualTo(drawable);
}
}

View File

@@ -1,79 +0,0 @@
/*
* 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;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import android.os.Looper;
import android.util.SparseArray;
import androidx.test.annotation.UiThreadTest;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.settings.deviceinfo.storage.StorageAsyncLoader;
import com.android.settings.deviceinfo.storage.StorageItemPreferenceController;
import com.android.settingslib.applications.StorageStatsSource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class)
public class StorageProfileFragmentTest {
@Captor
private ArgumentCaptor<SparseArray<StorageAsyncLoader.AppsStorageResult>> mCaptor;
@Test
@UiThreadTest
public void verifyAppSizesAreNotZeroedOut() {
if (Looper.myLooper() == null) {
Looper.prepare();
}
StorageItemPreferenceController controller = mock(StorageItemPreferenceController.class);
StorageProfileFragment fragment = new StorageProfileFragment();
StorageAsyncLoader.AppsStorageResult result = new StorageAsyncLoader.AppsStorageResult();
result.musicAppsSize = 100;
result.otherAppsSize = 200;
result.gamesSize = 300;
result.videoAppsSize = 400;
result.externalStats = new StorageStatsSource.ExternalStorageStats(6, 1, 2, 3, 0);
SparseArray<StorageAsyncLoader.AppsStorageResult> resultsArray = new SparseArray<>();
resultsArray.put(0, result);
fragment.setPreferenceController(controller);
fragment.onLoadFinished(null, resultsArray);
MockitoAnnotations.initMocks(this);
verify(controller).onLoadFinished(mCaptor.capture(), anyInt());
StorageAsyncLoader.AppsStorageResult extractedResult = mCaptor.getValue().get(0);
assertThat(extractedResult.musicAppsSize).isEqualTo(100);
assertThat(extractedResult.videoAppsSize).isEqualTo(400);
assertThat(extractedResult.otherAppsSize).isEqualTo(200);
assertThat(extractedResult.gamesSize).isEqualTo(300);
assertThat(extractedResult.externalStats.audioBytes).isEqualTo(1);
assertThat(extractedResult.externalStats.videoBytes).isEqualTo(2);
assertThat(extractedResult.externalStats.imageBytes).isEqualTo(3);
assertThat(extractedResult.externalStats.totalBytes).isEqualTo(6);
}
}