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