Merge "Use storage fast track to query packages in app info."
This commit is contained in:
@@ -19,9 +19,11 @@ package com.android.settings.applications;
|
|||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.AppGlobals;
|
import android.app.AppGlobals;
|
||||||
|
import android.app.LoaderManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.Loader;
|
||||||
import android.content.UriPermission;
|
import android.content.UriPermission;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.IPackageDataObserver;
|
import android.content.pm.IPackageDataObserver;
|
||||||
@@ -52,8 +54,9 @@ import com.android.settingslib.RestrictedLockUtils;
|
|||||||
import com.android.settingslib.applications.ApplicationsState;
|
import com.android.settingslib.applications.ApplicationsState;
|
||||||
import com.android.settingslib.applications.ApplicationsState.AppEntry;
|
import com.android.settingslib.applications.ApplicationsState.AppEntry;
|
||||||
import com.android.settingslib.applications.ApplicationsState.Callbacks;
|
import com.android.settingslib.applications.ApplicationsState.Callbacks;
|
||||||
|
import com.android.settingslib.applications.StorageStatsSource;
|
||||||
|
import com.android.settingslib.applications.StorageStatsSource.AppStorageStats;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -64,7 +67,8 @@ import static android.content.pm.ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
|
|||||||
import static android.content.pm.ApplicationInfo.FLAG_SYSTEM;
|
import static android.content.pm.ApplicationInfo.FLAG_SYSTEM;
|
||||||
|
|
||||||
public class AppStorageSettings extends AppInfoWithHeader
|
public class AppStorageSettings extends AppInfoWithHeader
|
||||||
implements OnClickListener, Callbacks, DialogInterface.OnClickListener {
|
implements OnClickListener, Callbacks, DialogInterface.OnClickListener,
|
||||||
|
LoaderManager.LoaderCallbacks<AppStorageStats> {
|
||||||
private static final String TAG = AppStorageSettings.class.getSimpleName();
|
private static final String TAG = AppStorageSettings.class.getSimpleName();
|
||||||
|
|
||||||
//internal constants used in Handler
|
//internal constants used in Handler
|
||||||
@@ -123,6 +127,7 @@ public class AppStorageSettings extends AppInfoWithHeader
|
|||||||
private boolean mCanClearData = true;
|
private boolean mCanClearData = true;
|
||||||
private boolean mHaveSizes = false;
|
private boolean mHaveSizes = false;
|
||||||
|
|
||||||
|
private AppStorageStats mLastResult;
|
||||||
private long mLastCodeSize = -1;
|
private long mLastCodeSize = -1;
|
||||||
private long mLastDataSize = -1;
|
private long mLastDataSize = -1;
|
||||||
private long mLastExternalCodeSize = -1;
|
private long mLastExternalCodeSize = -1;
|
||||||
@@ -139,6 +144,7 @@ public class AppStorageSettings extends AppInfoWithHeader
|
|||||||
|
|
||||||
private VolumeInfo[] mCandidates;
|
private VolumeInfo[] mCandidates;
|
||||||
private AlertDialog.Builder mDialogBuilder;
|
private AlertDialog.Builder mDialogBuilder;
|
||||||
|
private ApplicationInfo mInfo;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
@@ -152,7 +158,7 @@ public class AppStorageSettings extends AppInfoWithHeader
|
|||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
mState.requestSize(mPackageName, mUserId);
|
updateSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupViews() {
|
private void setupViews() {
|
||||||
@@ -266,79 +272,13 @@ public class AppStorageSettings extends AppInfoWithHeader
|
|||||||
return Formatter.formatFileSize(getActivity(), size);
|
return Formatter.formatFileSize(getActivity(), size);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void refreshSizeInfo() {
|
|
||||||
if (mAppEntry.size == ApplicationsState.SIZE_INVALID
|
|
||||||
|| mAppEntry.size == ApplicationsState.SIZE_UNKNOWN) {
|
|
||||||
mLastCodeSize = mLastDataSize = mLastCacheSize = mLastTotalSize = -1;
|
|
||||||
if (!mHaveSizes) {
|
|
||||||
mAppSize.setSummary(mComputingStr);
|
|
||||||
mDataSize.setSummary(mComputingStr);
|
|
||||||
mCacheSize.setSummary(mComputingStr);
|
|
||||||
mTotalSize.setSummary(mComputingStr);
|
|
||||||
}
|
|
||||||
mClearDataButton.setEnabled(false);
|
|
||||||
mClearCacheButton.setEnabled(false);
|
|
||||||
} else {
|
|
||||||
mHaveSizes = true;
|
|
||||||
long codeSize = mAppEntry.codeSize;
|
|
||||||
long dataSize = mAppEntry.dataSize;
|
|
||||||
if (Environment.isExternalStorageEmulated()) {
|
|
||||||
codeSize += mAppEntry.externalCodeSize;
|
|
||||||
dataSize += mAppEntry.externalDataSize;
|
|
||||||
} else {
|
|
||||||
if (mLastExternalCodeSize != mAppEntry.externalCodeSize) {
|
|
||||||
mLastExternalCodeSize = mAppEntry.externalCodeSize;
|
|
||||||
mExternalCodeSize.setSummary(getSizeStr(mAppEntry.externalCodeSize));
|
|
||||||
}
|
|
||||||
if (mLastExternalDataSize != mAppEntry.externalDataSize) {
|
|
||||||
mLastExternalDataSize = mAppEntry.externalDataSize;
|
|
||||||
mExternalDataSize.setSummary(getSizeStr( mAppEntry.externalDataSize));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mLastCodeSize != codeSize) {
|
|
||||||
mLastCodeSize = codeSize;
|
|
||||||
mAppSize.setSummary(getSizeStr(codeSize));
|
|
||||||
}
|
|
||||||
if (mLastDataSize != dataSize) {
|
|
||||||
mLastDataSize = dataSize;
|
|
||||||
mDataSize.setSummary(getSizeStr(dataSize));
|
|
||||||
}
|
|
||||||
long cacheSize = mAppEntry.cacheSize + mAppEntry.externalCacheSize;
|
|
||||||
if (mLastCacheSize != cacheSize) {
|
|
||||||
mLastCacheSize = cacheSize;
|
|
||||||
mCacheSize.setSummary(getSizeStr(cacheSize));
|
|
||||||
}
|
|
||||||
if (mLastTotalSize != mAppEntry.size) {
|
|
||||||
mLastTotalSize = mAppEntry.size;
|
|
||||||
mTotalSize.setSummary(getSizeStr(mAppEntry.size));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((mAppEntry.dataSize+ mAppEntry.externalDataSize) <= 0 || !mCanClearData) {
|
|
||||||
mClearDataButton.setEnabled(false);
|
|
||||||
} else {
|
|
||||||
mClearDataButton.setEnabled(true);
|
|
||||||
mClearDataButton.setOnClickListener(this);
|
|
||||||
}
|
|
||||||
if (cacheSize <= 0) {
|
|
||||||
mClearCacheButton.setEnabled(false);
|
|
||||||
} else {
|
|
||||||
mClearCacheButton.setEnabled(true);
|
|
||||||
mClearCacheButton.setOnClickListener(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mAppsControlDisallowedBySystem) {
|
|
||||||
mClearCacheButton.setEnabled(false);
|
|
||||||
mClearDataButton.setEnabled(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean refreshUi() {
|
protected boolean refreshUi() {
|
||||||
retrieveAppEntry();
|
retrieveAppEntry();
|
||||||
if (mAppEntry == null) {
|
if (mAppEntry == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
refreshSizeInfo();
|
updateUiWithSize(mLastResult);
|
||||||
refreshGrantedUriPermissions();
|
refreshGrantedUriPermissions();
|
||||||
|
|
||||||
final VolumeInfo currentVol = getActivity().getPackageManager()
|
final VolumeInfo currentVol = getActivity().getPackageManager()
|
||||||
@@ -454,7 +394,7 @@ public class AppStorageSettings extends AppInfoWithHeader
|
|||||||
mClearDataButton.setText(R.string.clear_user_data_text);
|
mClearDataButton.setText(R.string.clear_user_data_text);
|
||||||
if (result == OP_SUCCESSFUL) {
|
if (result == OP_SUCCESSFUL) {
|
||||||
Log.i(TAG, "Cleared user data for package : "+packageName);
|
Log.i(TAG, "Cleared user data for package : "+packageName);
|
||||||
mState.requestSize(mPackageName, mUserId);
|
updateSize();
|
||||||
} else {
|
} else {
|
||||||
mClearDataButton.setEnabled(true);
|
mClearDataButton.setEnabled(true);
|
||||||
}
|
}
|
||||||
@@ -570,8 +510,91 @@ public class AppStorageSettings extends AppInfoWithHeader
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPackageSizeChanged(String packageName) {
|
public void onPackageSizeChanged(String packageName) {
|
||||||
if (packageName.equals(mAppEntry.info.packageName)) {
|
}
|
||||||
refreshSizeInfo();
|
|
||||||
|
@Override
|
||||||
|
public Loader<AppStorageStats> onCreateLoader(int id, Bundle args) {
|
||||||
|
Context context = getContext();
|
||||||
|
return new FetchPackageStorageAsyncLoader(
|
||||||
|
context, new StorageStatsSource(context), mInfo, UserHandle.of(mUserId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoadFinished(Loader<AppStorageStats> loader, AppStorageStats result) {
|
||||||
|
mLastResult = result;
|
||||||
|
updateUiWithSize(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoaderReset(Loader<AppStorageStats> loader) {
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateSize() {
|
||||||
|
PackageManager packageManager = getPackageManager();
|
||||||
|
try {
|
||||||
|
mInfo = packageManager.getApplicationInfo(mPackageName, 0);
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
Log.e(TAG, "Could not find package", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mInfo == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
getLoaderManager().restartLoader(1, Bundle.EMPTY, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateUiWithSize(AppStorageStats result) {
|
||||||
|
if (result == null) {
|
||||||
|
mLastCodeSize = mLastDataSize = mLastCacheSize = mLastTotalSize = -1;
|
||||||
|
if (!mHaveSizes) {
|
||||||
|
mAppSize.setSummary(mComputingStr);
|
||||||
|
mDataSize.setSummary(mComputingStr);
|
||||||
|
mCacheSize.setSummary(mComputingStr);
|
||||||
|
mTotalSize.setSummary(mComputingStr);
|
||||||
|
}
|
||||||
|
mClearDataButton.setEnabled(false);
|
||||||
|
mClearCacheButton.setEnabled(false);
|
||||||
|
} else {
|
||||||
|
mHaveSizes = true;
|
||||||
|
long codeSize = result.getCodeBytes();
|
||||||
|
long dataSize = result.getDataBytes();
|
||||||
|
if (mLastCodeSize != codeSize) {
|
||||||
|
mLastCodeSize = codeSize;
|
||||||
|
mAppSize.setSummary(getSizeStr(codeSize));
|
||||||
|
}
|
||||||
|
if (mLastDataSize != dataSize) {
|
||||||
|
mLastDataSize = dataSize;
|
||||||
|
mDataSize.setSummary(getSizeStr(dataSize));
|
||||||
|
}
|
||||||
|
long cacheSize = result.getCacheBytes();
|
||||||
|
if (mLastCacheSize != cacheSize) {
|
||||||
|
mLastCacheSize = cacheSize;
|
||||||
|
mCacheSize.setSummary(getSizeStr(cacheSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
long totalSize = codeSize + dataSize + cacheSize;
|
||||||
|
if (mLastTotalSize != totalSize) {
|
||||||
|
mLastTotalSize = totalSize;
|
||||||
|
mTotalSize.setSummary(getSizeStr(totalSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dataSize <= 0 || !mCanClearData) {
|
||||||
|
mClearDataButton.setEnabled(false);
|
||||||
|
} else {
|
||||||
|
mClearDataButton.setEnabled(true);
|
||||||
|
mClearDataButton.setOnClickListener(this);
|
||||||
|
}
|
||||||
|
if (cacheSize <= 0) {
|
||||||
|
mClearCacheButton.setEnabled(false);
|
||||||
|
} else {
|
||||||
|
mClearCacheButton.setEnabled(true);
|
||||||
|
mClearCacheButton.setOnClickListener(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mAppsControlDisallowedBySystem) {
|
||||||
|
mClearCacheButton.setEnabled(false);
|
||||||
|
mClearDataButton.setEnabled(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -586,7 +609,7 @@ public class AppStorageSettings extends AppInfoWithHeader
|
|||||||
break;
|
break;
|
||||||
case MSG_CLEAR_CACHE:
|
case MSG_CLEAR_CACHE:
|
||||||
// Refresh size info
|
// Refresh size info
|
||||||
mState.requestSize(mPackageName, mUserId);
|
updateSize();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* 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.applications;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.os.UserHandle;
|
||||||
|
|
||||||
|
import com.android.internal.util.Preconditions;
|
||||||
|
import com.android.settings.utils.AsyncLoader;
|
||||||
|
import com.android.settingslib.applications.StorageStatsSource;
|
||||||
|
import com.android.settingslib.applications.StorageStatsSource.AppStorageStats;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the storage stats using the StorageStatsManager for a given package and user tuple.
|
||||||
|
*/
|
||||||
|
public class FetchPackageStorageAsyncLoader extends AsyncLoader<AppStorageStats> {
|
||||||
|
private final StorageStatsSource mSource;
|
||||||
|
private final ApplicationInfo mInfo;
|
||||||
|
private final UserHandle mUser;
|
||||||
|
|
||||||
|
public FetchPackageStorageAsyncLoader(Context context, @NonNull StorageStatsSource source,
|
||||||
|
@NonNull ApplicationInfo info, @NonNull UserHandle user) {
|
||||||
|
super(context);
|
||||||
|
mSource = Preconditions.checkNotNull(source);
|
||||||
|
mInfo = info;
|
||||||
|
mUser = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AppStorageStats loadInBackground() {
|
||||||
|
return mSource.getStatsForPackage(mInfo.volumeUuid, mInfo.packageName, mUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDiscardResult(AppStorageStats result) {
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* 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.applications;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import static org.mockito.Matchers.any;
|
||||||
|
import static org.mockito.Matchers.anyString;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.os.UserHandle;
|
||||||
|
|
||||||
|
import com.android.settings.SettingsRobolectricTestRunner;
|
||||||
|
import com.android.settings.TestConfig;
|
||||||
|
import com.android.settingslib.applications.StorageStatsSource;
|
||||||
|
import com.android.settingslib.applications.StorageStatsSource.AppStorageStats;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Answers;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
|
||||||
|
@RunWith(SettingsRobolectricTestRunner.class)
|
||||||
|
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||||
|
public class FetchPackageStorageAsyncLoaderTest {
|
||||||
|
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||||
|
private Context mContext;
|
||||||
|
@Mock
|
||||||
|
private StorageStatsSource mSource;
|
||||||
|
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void worksForValidPackageNameAndUid() {
|
||||||
|
AppStorageStats stats = mock(AppStorageStats.class);
|
||||||
|
when(stats.getCodeBytes()).thenReturn(1L);
|
||||||
|
when(stats.getDataBytes()).thenReturn(2L);
|
||||||
|
when(stats.getCacheBytes()).thenReturn(3L);
|
||||||
|
when(mSource.getStatsForPackage(anyString(), anyString(), any(UserHandle.class)))
|
||||||
|
.thenReturn(stats);
|
||||||
|
ApplicationInfo info = new ApplicationInfo();
|
||||||
|
info.packageName = "com.test.package";
|
||||||
|
|
||||||
|
FetchPackageStorageAsyncLoader task = new FetchPackageStorageAsyncLoader(
|
||||||
|
mContext, mSource, info, new UserHandle(0));
|
||||||
|
assertThat(task.loadInBackground()).isEqualTo(stats);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user