1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package com.android.settings.applications;
18 
19 import android.content.Context;
20 import android.text.format.Formatter;
21 
22 import androidx.annotation.Nullable;
23 import androidx.annotation.StringRes;
24 import androidx.preference.Preference;
25 
26 import com.android.internal.util.Preconditions;
27 import com.android.settingslib.applications.StorageStatsSource;
28 
29 /**
30  * Handles setting the sizes for the app info screen.
31  */
32 public class AppStorageSizesController {
33     private final Preference mTotalSize;
34     private final Preference mAppSize;
35     private final Preference mDataSize;
36     private final Preference mCacheSize;
37     private final @StringRes int mComputing;
38     private final @StringRes int mError;
39 
40     @Nullable
41     private StorageStatsSource.AppStorageStats mLastResult;
42     private boolean mLastResultFailed;
43     private boolean mCachedCleared;
44     private boolean mDataCleared;
45     private long mLastCodeSize = -1;
46     private long mLastDataSize = -1;
47     private long mLastCacheSize = -1;
48     private long mLastTotalSize = -1;
49 
AppStorageSizesController(Preference total, Preference app, Preference data, Preference cache, @StringRes int computing, @StringRes int error)50     private AppStorageSizesController(Preference total, Preference app,
51             Preference data, Preference cache, @StringRes int computing, @StringRes int error) {
52         mTotalSize = total;
53         mAppSize = app;
54         mDataSize = data;
55         mCacheSize = cache;
56         mComputing = computing;
57         mError = error;
58     }
59 
60     /**
61      * Updates the UI using storage stats.
62      * @param context Context to use to fetch strings
63      */
updateUi(Context context)64     public void updateUi(Context context) {
65         if (mLastResult == null) {
66             int errorRes = mLastResultFailed ? mError : mComputing;
67 
68             mAppSize.setSummary(errorRes);
69             mDataSize.setSummary(errorRes);
70             mCacheSize.setSummary(errorRes);
71             mTotalSize.setSummary(errorRes);
72         } else {
73             long codeSize = mLastResult.getCodeBytes();
74             long dataSize =
75                     mDataCleared ? 0 : mLastResult.getDataBytes() - mLastResult.getCacheBytes();
76             if (mLastCodeSize != codeSize) {
77                 mLastCodeSize = codeSize;
78                 mAppSize.setSummary(getSizeStr(context, codeSize));
79             }
80             if (mLastDataSize != dataSize) {
81                 mLastDataSize = dataSize;
82                 mDataSize.setSummary(getSizeStr(context, dataSize));
83             }
84             long cacheSize = (mDataCleared || mCachedCleared) ? 0 : mLastResult.getCacheBytes();
85             if (mLastCacheSize != cacheSize) {
86                 mLastCacheSize = cacheSize;
87                 mCacheSize.setSummary(getSizeStr(context, cacheSize));
88             }
89 
90             long totalSize = codeSize + dataSize + cacheSize;
91             if (mLastTotalSize != totalSize) {
92                 mLastTotalSize = totalSize;
93                 mTotalSize.setSummary(getSizeStr(context, totalSize));
94             }
95         }
96     }
97 
98     /**
99      * Sets a result for the controller to use to update the UI.
100      * @param result A result for the UI. If null, count as a failed calculation.
101      */
setResult(StorageStatsSource.AppStorageStats result)102     public void setResult(StorageStatsSource.AppStorageStats result) {
103         mLastResult = result;
104         mLastResultFailed = result == null;
105     }
106 
107     /**
108      * Sets if we have cleared the cache and should zero the cache bytes.
109      * When the cache is cleared, the cache directories are recreated. These directories have
110      * some size, but are empty. We zero this out to best match user expectations.
111      */
setCacheCleared(boolean isCleared)112     public void setCacheCleared(boolean isCleared) {
113         mCachedCleared = isCleared;
114     }
115 
116     /**
117      * Sets if we have cleared data and should zero the data bytes.
118      * When the data is cleared, the directory are recreated. Directories have some size, but are
119      * empty. We zero this out to best match user expectations.
120      */
setDataCleared(boolean isCleared)121     public void setDataCleared(boolean isCleared) {
122         mDataCleared = isCleared;
123     }
124 
125     /**
126      * Returns the last result calculated, if it exists. If it does not, returns null.
127      */
getLastResult()128     public StorageStatsSource.AppStorageStats getLastResult() {
129         return mLastResult;
130     }
131 
getSizeStr(Context context, long size)132     private String getSizeStr(Context context, long size) {
133         return Formatter.formatFileSize(context, size);
134     }
135 
136     public static class Builder {
137         private Preference mTotalSize;
138         private Preference mAppSize;
139         private Preference mDataSize;
140         private Preference mCacheSize;
141         private @StringRes int mComputing;
142         private @StringRes int mError;
143 
setAppSizePreference(Preference preference)144         public Builder setAppSizePreference(Preference preference) {
145             mAppSize = preference;
146             return this;
147         }
148 
setDataSizePreference(Preference preference)149         public Builder setDataSizePreference(Preference preference) {
150             mDataSize = preference;
151             return this;
152         }
153 
setCacheSizePreference(Preference preference)154         public Builder setCacheSizePreference(Preference preference) {
155             mCacheSize = preference;
156             return this;
157         }
158 
setTotalSizePreference(Preference preference)159         public Builder setTotalSizePreference(Preference preference) {
160             mTotalSize = preference;
161             return this;
162         }
163 
setComputingString(@tringRes int sequence)164         public Builder setComputingString(@StringRes int sequence) {
165             mComputing = sequence;
166             return this;
167         }
168 
setErrorString(@tringRes int sequence)169         public Builder setErrorString(@StringRes int sequence) {
170             mError = sequence;
171             return this;
172         }
173 
build()174         public AppStorageSizesController build() {
175             return new AppStorageSizesController(
176                     Preconditions.checkNotNull(mTotalSize),
177                     Preconditions.checkNotNull(mAppSize),
178                     Preconditions.checkNotNull(mDataSize),
179                     Preconditions.checkNotNull(mCacheSize),
180                     mComputing,
181                     mError);
182         }
183     }
184 }
185