Fix a crash when transferring an app.

This crash occurs because the background loader is loading
the storage for an app which is currently being moved off of
the device. In the native code which is calculating the storage,
it throws an InstallerException which is caught and rethrown as an
IllegalStateException.

We handle this in the view by reporting that we could not calculate
the size of the app.

Change-Id: I109b1be60ae60f8ef31b08cb4392b576261fa806
Fixes: 35922033
Test: Robotest
This commit is contained in:
Daniel Nishi
2017-03-02 12:52:40 -08:00
parent 8e12df9d62
commit 6a256e77d6
6 changed files with 285 additions and 71 deletions

View File

@@ -0,0 +1,95 @@
package com.android.settings.applications;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.support.v7.preference.Preference;
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;
import com.android.settings.R;
import com.android.settingslib.applications.StorageStatsSource.AppStorageStats;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class AppStorageSizesControllerTest {
private static final String COMPUTING = "Computing…";
private static final String INVALID_SIZE = "Couldnt compute package size.";
private AppStorageSizesController mController;
private Context mContext;
private Preference mAppPreference;
private Preference mCachePreference;
private Preference mDataPreference;
private Preference mTotalPreference;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mAppPreference = new Preference(mContext);
mCachePreference = new Preference(mContext);
mDataPreference = new Preference(mContext);
mTotalPreference = new Preference(mContext);
mController = new AppStorageSizesController.Builder()
.setAppSizePreference(mAppPreference)
.setCacheSizePreference(mCachePreference)
.setDataSizePreference(mDataPreference)
.setTotalSizePreference(mTotalPreference)
.setErrorString(R.string.invalid_size_value)
.setComputingString(R.string.computing_size)
.build();
}
@Test
public void requestingUpdateBeforeValuesSetIsComputing() {
mController.updateUi(mContext);
assertThat(mAppPreference.getSummary()).isEqualTo(COMPUTING);
assertThat(mCachePreference.getSummary()).isEqualTo(COMPUTING);
assertThat(mDataPreference.getSummary()).isEqualTo(COMPUTING);
assertThat(mTotalPreference.getSummary()).isEqualTo(COMPUTING);
}
@Test
public void requestingUpdateAfterFailureHasErrorText() {
mController.setResult(null);
mController.updateUi(mContext);
assertThat(mAppPreference.getSummary()).isEqualTo(INVALID_SIZE);
assertThat(mCachePreference.getSummary()).isEqualTo(INVALID_SIZE);
assertThat(mDataPreference.getSummary()).isEqualTo(INVALID_SIZE);
assertThat(mTotalPreference.getSummary()).isEqualTo(INVALID_SIZE);
}
@Test
public void properlyPopulatedAfterValidEntry() {
AppStorageStats result = mock(AppStorageStats.class);
when(result.getCodeBytes()).thenReturn(1L);
when(result.getCacheBytes()).thenReturn(10L);
when(result.getDataBytes()).thenReturn(100L);
when(result.getTotalBytes()).thenReturn(111L);
mController.setResult(result);
mController.updateUi(mContext);
assertThat(mAppPreference.getSummary()).isEqualTo("1.00B");
assertThat(mCachePreference.getSummary()).isEqualTo("10.00B");
assertThat(mDataPreference.getSummary()).isEqualTo("100B");
assertThat(mTotalPreference.getSummary()).isEqualTo("111B");
}
}

View File

@@ -43,6 +43,7 @@ import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class FetchPackageStorageAsyncLoaderTest {
private static final String PACKAGE_NAME = "com.test.package";
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mContext;
@Mock
@@ -63,10 +64,22 @@ public class FetchPackageStorageAsyncLoaderTest {
when(mSource.getStatsForPackage(anyString(), anyString(), any(UserHandle.class)))
.thenReturn(stats);
ApplicationInfo info = new ApplicationInfo();
info.packageName = "com.test.package";
info.packageName = PACKAGE_NAME;
FetchPackageStorageAsyncLoader task = new FetchPackageStorageAsyncLoader(
mContext, mSource, info, new UserHandle(0));
assertThat(task.loadInBackground()).isEqualTo(stats);
}
@Test
public void installerExceptionHandledCleanly() {
when(mSource.getStatsForPackage(anyString(), anyString(), any(UserHandle.class))).
thenThrow(new IllegalStateException("intentional failure"));
ApplicationInfo info = new ApplicationInfo();
info.packageName = PACKAGE_NAME;
FetchPackageStorageAsyncLoader task = new FetchPackageStorageAsyncLoader(
mContext, mSource, info, new UserHandle(0));
assertThat(task.loadInBackground()).isNull();
}
}