• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 android.app.usage;
18 
19 import android.annotation.BytesLong;
20 import android.annotation.FlaggedApi;
21 import android.annotation.IntDef;
22 import android.content.Context;
23 import android.os.Parcel;
24 import android.os.Parcelable;
25 import android.os.RemoteException;
26 import android.os.ServiceManager;
27 import android.os.UserHandle;
28 import android.util.Log;
29 
30 import java.lang.annotation.Retention;
31 import java.lang.annotation.RetentionPolicy;
32 
33 /**
34  * Storage statistics for a UID, package, or {@link UserHandle} on a single
35  * storage volume.
36  *
37  * @see StorageStatsManager
38  */
39 public final class StorageStats implements Parcelable {
40     /** @hide */ public String packageName;
41     /** @hide */ public int userHandle;
42     /** @hide */ public int uid;
43     /** @hide */ public long codeBytes;
44     /** @hide */ public long dataBytes;
45     /** @hide */ public long cacheBytes;
46     /** @hide */ public long apkBytes;
47     /** @hide */ public long libBytes;
48     /** @hide */ public long dmBytes;
49     /** @hide */ public long dexoptBytes;
50     /** @hide */ public long curProfBytes;
51     /** @hide */ public long refProfBytes;
52     /** @hide */ public long externalCacheBytes;
53 
54     /**
55      * Represents all nonstale dexopt and runtime artifacts of application.
56      * This includes AOT-compiled code and other data that can speed up app execution.
57      * For more detailed information, read the
58      * <a href="https://source.android.com/docs/core/runtime/jit-compiler#flow">JIT compiler</a>
59      * guide.
60      *
61      * Dexopt artifacts become stale when one of their dependencies
62      * has changed. They may be cleaned up or replaced by ART Services at any time.
63      *
64      * For a preload app, this type includes dexopt artifacts on readonly partitions
65      * if they are up-to-date.
66      *
67      * Can be used as an input to {@link #getAppBytesByDataType(int)}
68      * to get the sum of sizes for files of this type. The sum might include the size of data
69      * that is part of appBytes, dataBytes or cacheBytes.
70      */
71     @FlaggedApi(Flags.FLAG_GET_APP_BYTES_BY_DATA_TYPE_API)
72     public static final int APP_DATA_TYPE_FILE_TYPE_DEXOPT_ARTIFACT = 0;
73 
74     /**
75      * Represents reference profile of application.
76      *
77      * Reference profiles are the ones used during the last profile-guided dexopt.
78      * If the last dexopt wasn't profile-guided, then these profiles were not used.
79      *
80      * Can be used as an input to {@link #getAppBytesByDataType(int)}
81      * to get the size of files of this type.
82      */
83     @FlaggedApi(Flags.FLAG_GET_APP_BYTES_BY_DATA_TYPE_API)
84     public static final int APP_DATA_TYPE_FILE_TYPE_REFERENCE_PROFILE = 1;
85 
86     /**
87      * Represents current profile of application.
88      *
89      * Current profiles may or may not be used during the next profile-guided dexopt.
90      *
91      * Can be used as an input to {@link #getAppBytesByDataType(int)}
92      * to get the size of files of this type. This size fluctuates regularly,
93      * it goes up when the user uses more and more classes/methods and comes down when
94      * a deamon merges this into the ref profile and does profile-guided dexopt.
95      */
96     @FlaggedApi(Flags.FLAG_GET_APP_BYTES_BY_DATA_TYPE_API)
97     public static final int APP_DATA_TYPE_FILE_TYPE_CURRENT_PROFILE = 2;
98 
99     /**
100      * Represents all .apk files in application code path.
101      * Can be used as an input to {@link #getAppBytesByDataType(int)}
102      * to get the sum of sizes for files of this type.
103      */
104     @FlaggedApi(Flags.FLAG_GET_APP_BYTES_BY_DATA_TYPE_API)
105     public static final int APP_DATA_TYPE_FILE_TYPE_APK = 3;
106 
107     /**
108      * Represents all .dm files in application code path.
109      * Can be used as an input to {@link #getAppBytesByDataType(int)}
110      * to get the sum of sizes for files of this type.
111      */
112     @FlaggedApi(Flags.FLAG_GET_APP_BYTES_BY_DATA_TYPE_API)
113     public static final int APP_DATA_TYPE_FILE_TYPE_DM = 4;
114 
115     /**
116      * Represents lib/ in application code path.
117      * Can be used as an input to {@link #getAppBytesByDataType(int)}
118      * to get the size of lib/ directory.
119      */
120     @FlaggedApi(Flags.FLAG_GET_APP_BYTES_BY_DATA_TYPE_API)
121     public static final int APP_DATA_TYPE_LIB = 5;
122 
123     /**
124      * Keep in sync with the file types defined above.
125      * @hide
126      */
127     @FlaggedApi(Flags.FLAG_GET_APP_BYTES_BY_DATA_TYPE_API)
128     @IntDef(flag = false, value = {
129         APP_DATA_TYPE_FILE_TYPE_DEXOPT_ARTIFACT,
130         APP_DATA_TYPE_FILE_TYPE_REFERENCE_PROFILE,
131         APP_DATA_TYPE_FILE_TYPE_CURRENT_PROFILE,
132         APP_DATA_TYPE_FILE_TYPE_APK,
133         APP_DATA_TYPE_FILE_TYPE_DM,
134         APP_DATA_TYPE_LIB,
135     })
136     @Retention(RetentionPolicy.SOURCE)
137     public @interface AppDataType {}
138 
139     private static final String TAG = "StorageStats";
140 
141     /**
142      * artStatsFetched is only applicable when
143      * Flags.getAppArtManagedBytes() is true;
144      */
145     private boolean artStatsFetched;
146 
147     /**
148      * Return the size of app. This includes {@code APK} files, optimized
149      * compiler output, and unpacked native libraries.
150      * <p>
151      * If the primary external/shared storage is hosted on this storage device,
152      * then this includes files stored under {@link Context#getObbDir()}.
153      * <p>
154      * Code is shared between all users on a multiuser device.
155      */
getAppBytes()156     public @BytesLong long getAppBytes() {
157         return codeBytes;
158     }
159 
160     /**
161      * Return the size of the specified data type. This includes files stored under
162      * application code path.
163      * <p>
164      * If there is more than one package inside a uid, the return represents the aggregated
165      * stats when query StorageStat for package or uid.
166      * The data  is not collected and the return defaults to 0 when query StorageStats for user.
167      *
168      * <p>
169      * Data is isolated for each user on a multiuser device.
170      */
171     @FlaggedApi(Flags.FLAG_GET_APP_BYTES_BY_DATA_TYPE_API)
getAppBytesByDataType(@ppDataType int dataType)172     public long getAppBytesByDataType(@AppDataType int dataType) {
173         switch (dataType) {
174           case APP_DATA_TYPE_FILE_TYPE_DEXOPT_ARTIFACT: return getDexoptBytes();
175           case APP_DATA_TYPE_FILE_TYPE_REFERENCE_PROFILE: return getRefProfBytes();
176           case APP_DATA_TYPE_FILE_TYPE_CURRENT_PROFILE: return getCurProfBytes();
177           case APP_DATA_TYPE_FILE_TYPE_APK: return apkBytes;
178           case APP_DATA_TYPE_LIB: return libBytes;
179           case APP_DATA_TYPE_FILE_TYPE_DM: return dmBytes;
180           default: return 0;
181         }
182     }
183 
184     /**
185      * Return the size of all data. This includes files stored under
186      * {@link Context#getDataDir()}, {@link Context#getCacheDir()},
187      * {@link Context#getCodeCacheDir()}.
188      * <p>
189      * If the primary external/shared storage is hosted on this storage device,
190      * then this includes files stored under
191      * {@link Context#getExternalFilesDir(String)},
192      * {@link Context#getExternalCacheDir()}, and
193      * {@link Context#getExternalMediaDirs()}.
194      * <p>
195      * Data is isolated for each user on a multiuser device.
196      */
getDataBytes()197     public @BytesLong long getDataBytes() {
198         return dataBytes;
199     }
200 
201     /**
202      * Return the size of all cached data. This includes files stored under
203      * {@link Context#getCacheDir()} and {@link Context#getCodeCacheDir()}.
204      * <p>
205      * If the primary external/shared storage is hosted on this storage device,
206      * then this includes files stored under
207      * {@link Context#getExternalCacheDir()}.
208      * <p>
209      * Cached data is isolated for each user on a multiuser device.
210      */
getCacheBytes()211     public @BytesLong long getCacheBytes() {
212         return cacheBytes;
213     }
214 
215     /**
216      * Return the size of all cached data in the primary external/shared storage.
217      * This includes files stored under
218      * {@link Context#getExternalCacheDir()}.
219      * <p>
220      * Cached data is isolated for each user on a multiuser device.
221      */
getExternalCacheBytes()222     public @BytesLong long getExternalCacheBytes() {
223         return externalCacheBytes;
224     }
225 
226     /** {@hide} */
StorageStats()227     public StorageStats() {
228     }
229 
230     /** {@hide} */
StorageStats(Parcel in)231     public StorageStats(Parcel in) {
232         this.packageName = in.readString8();
233         this.userHandle = in.readInt();
234         this.uid = in.readInt();
235         this.codeBytes = in.readLong();
236         this.dataBytes = in.readLong();
237         this.cacheBytes = in.readLong();
238         this.dexoptBytes = in.readLong();
239         this.refProfBytes = in.readLong();
240         this.curProfBytes = in.readLong();
241         this.apkBytes = in.readLong();
242         this.libBytes = in.readLong();
243         this.dmBytes = in.readLong();
244         this.externalCacheBytes = in.readLong();
245     }
246 
247     @Override
describeContents()248     public int describeContents() {
249         return 0;
250     }
251 
252     @Override
writeToParcel(Parcel dest, int flags)253     public void writeToParcel(Parcel dest, int flags) {
254         dest.writeString8(packageName);
255         dest.writeInt(userHandle);
256         dest.writeInt(uid);
257         dest.writeLong(codeBytes);
258         dest.writeLong(dataBytes);
259         dest.writeLong(cacheBytes);
260         dest.writeLong(dexoptBytes);
261         dest.writeLong(refProfBytes);
262         dest.writeLong(curProfBytes);
263         dest.writeLong(apkBytes);
264         dest.writeLong(libBytes);
265         dest.writeLong(dmBytes);
266         dest.writeLong(externalCacheBytes);
267     }
268 
269     public static final @android.annotation.NonNull Creator<StorageStats> CREATOR = new Creator<StorageStats>() {
270         @Override
271         public StorageStats createFromParcel(Parcel in) {
272             return new StorageStats(in);
273         }
274 
275         @Override
276         public StorageStats[] newArray(int size) {
277             return new StorageStats[size];
278         }
279     };
280 
getArtManagedStats()281     private void getArtManagedStats() {
282       try {
283         IStorageStatsManager storageStatsManagerService;
284         // Fetch art stats only if it is not already fetched.
285         if (Flags.getAppArtManagedBytes() && !artStatsFetched) {
286           android.os.IBinder binder = ServiceManager.getService("storagestats");
287           storageStatsManagerService = IStorageStatsManager.Stub.asInterface(binder);
288 
289           StorageStats newStats =
290               storageStatsManagerService.queryArtManagedStats(packageName, userHandle, uid);
291 
292           dexoptBytes = newStats.dexoptBytes;
293           curProfBytes = newStats.curProfBytes;
294           refProfBytes = newStats.refProfBytes;
295 
296           artStatsFetched = true;
297         }
298       } catch (RemoteException e) {
299           Log.e(TAG, "Failed to get art stats", e);
300           e.rethrowFromSystemServer();
301       }
302     }
303 
getDexoptBytes()304     private long getDexoptBytes() {
305       getArtManagedStats();
306       return dexoptBytes;
307     }
308 
getCurProfBytes()309     private long getCurProfBytes() {
310       getArtManagedStats();
311       return curProfBytes;
312     }
313 
getRefProfBytes()314     private long getRefProfBytes() {
315       getArtManagedStats();
316       return refProfBytes;
317     }
318 }
319