OSDN Git Service

Use storage fast track to query packages in app info.
authorDaniel Nishi <dhnishi@google.com>
Fri, 24 Feb 2017 21:59:49 +0000 (13:59 -0800)
committerDaniel Nishi <dhnishi@google.com>
Wed, 1 Mar 2017 02:36:34 +0000 (18:36 -0800)
App info used to use the old ApplicationsState path. This
removes the size query and replaces it with an AsyncTask to
load the sizes.

Fixes: 35805032
Test: Robotest
Change-Id: Ica1c88da2b407c3cbd4d7f970c7c44e4064393b3

src/com/android/settings/applications/AppStorageSettings.java
src/com/android/settings/applications/FetchPackageStorageAsyncLoader.java [new file with mode: 0644]
tests/robotests/src/com/android/settings/applications/FetchPackageStorageAsyncLoaderTest.java [new file with mode: 0644]

index e97a9ac..b4d7526 100644 (file)
@@ -19,9 +19,11 @@ package com.android.settings.applications;
 import android.app.ActivityManager;
 import android.app.AlertDialog;
 import android.app.AppGlobals;
+import android.app.LoaderManager;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
+import android.content.Loader;
 import android.content.UriPermission;
 import android.content.pm.ApplicationInfo;
 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.AppEntry;
 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.List;
 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;
 
 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();
 
     //internal constants used in Handler
@@ -123,6 +127,7 @@ public class AppStorageSettings extends AppInfoWithHeader
     private boolean mCanClearData = true;
     private boolean mHaveSizes = false;
 
+    private AppStorageStats mLastResult;
     private long mLastCodeSize = -1;
     private long mLastDataSize = -1;
     private long mLastExternalCodeSize = -1;
@@ -139,6 +144,7 @@ public class AppStorageSettings extends AppInfoWithHeader
 
     private VolumeInfo[] mCandidates;
     private AlertDialog.Builder mDialogBuilder;
+    private ApplicationInfo mInfo;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
@@ -152,7 +158,7 @@ public class AppStorageSettings extends AppInfoWithHeader
     @Override
     public void onResume() {
         super.onResume();
-        mState.requestSize(mPackageName, mUserId);
+        updateSize();
     }
 
     private void setupViews() {
@@ -266,79 +272,13 @@ public class AppStorageSettings extends AppInfoWithHeader
         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
     protected boolean refreshUi() {
         retrieveAppEntry();
         if (mAppEntry == null) {
             return false;
         }
-        refreshSizeInfo();
+        updateUiWithSize(mLastResult);
         refreshGrantedUriPermissions();
 
         final VolumeInfo currentVol = getActivity().getPackageManager()
@@ -454,7 +394,7 @@ public class AppStorageSettings extends AppInfoWithHeader
         mClearDataButton.setText(R.string.clear_user_data_text);
         if (result == OP_SUCCESSFUL) {
             Log.i(TAG, "Cleared user data for package : "+packageName);
-            mState.requestSize(mPackageName, mUserId);
+            updateSize();
         } else {
             mClearDataButton.setEnabled(true);
         }
@@ -570,8 +510,91 @@ public class AppStorageSettings extends AppInfoWithHeader
 
     @Override
     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;
                 case MSG_CLEAR_CACHE:
                     // Refresh size info
-                    mState.requestSize(mPackageName, mUserId);
+                    updateSize();
                     break;
             }
         }
diff --git a/src/com/android/settings/applications/FetchPackageStorageAsyncLoader.java b/src/com/android/settings/applications/FetchPackageStorageAsyncLoader.java
new file mode 100644 (file)
index 0000000..3477299
--- /dev/null
@@ -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) {
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/applications/FetchPackageStorageAsyncLoaderTest.java b/tests/robotests/src/com/android/settings/applications/FetchPackageStorageAsyncLoaderTest.java
new file mode 100644 (file)
index 0000000..0b1d1aa
--- /dev/null
@@ -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);
+    }
+}