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 static android.os.storage.StorageManager.convert; 20 21 import android.annotation.BytesLong; 22 import android.annotation.NonNull; 23 import android.annotation.SystemService; 24 import android.annotation.TestApi; 25 import android.annotation.WorkerThread; 26 import android.content.Context; 27 import android.content.pm.ApplicationInfo; 28 import android.content.pm.PackageInfo; 29 import android.content.pm.PackageManager; 30 import android.os.ParcelableException; 31 import android.os.RemoteException; 32 import android.os.UserHandle; 33 import android.os.storage.StorageManager; 34 35 import com.android.internal.util.Preconditions; 36 37 import java.io.File; 38 import java.io.IOException; 39 import java.util.UUID; 40 41 /** 42 * Access to detailed storage statistics. This provides a summary of how apps, 43 * users, and external/shared storage is utilizing disk space. 44 * <p class="note"> 45 * Note: no permissions are required when calling these APIs for your own 46 * package or UID. However, requesting details for any other package requires 47 * the {@code android.Manifest.permission#PACKAGE_USAGE_STATS} permission, which 48 * is a system-level permission that will not be granted to normal apps. 49 * Declaring that permission expresses your intention to use this API and an end 50 * user can then choose to grant this permission through the Settings 51 * application. 52 * </p> 53 */ 54 @SystemService(Context.STORAGE_STATS_SERVICE) 55 public class StorageStatsManager { 56 private final Context mContext; 57 private final IStorageStatsManager mService; 58 59 /** {@hide} */ StorageStatsManager(Context context, IStorageStatsManager service)60 public StorageStatsManager(Context context, IStorageStatsManager service) { 61 mContext = Preconditions.checkNotNull(context); 62 mService = Preconditions.checkNotNull(service); 63 } 64 65 /** {@hide} */ 66 @TestApi isQuotaSupported(@onNull UUID storageUuid)67 public boolean isQuotaSupported(@NonNull UUID storageUuid) { 68 try { 69 return mService.isQuotaSupported(convert(storageUuid), mContext.getOpPackageName()); 70 } catch (RemoteException e) { 71 throw e.rethrowFromSystemServer(); 72 } 73 } 74 75 /** @removed */ 76 @Deprecated isQuotaSupported(String uuid)77 public boolean isQuotaSupported(String uuid) { 78 return isQuotaSupported(convert(uuid)); 79 } 80 81 /** {@hide} */ 82 @TestApi isReservedSupported(@onNull UUID storageUuid)83 public boolean isReservedSupported(@NonNull UUID storageUuid) { 84 try { 85 return mService.isReservedSupported(convert(storageUuid), mContext.getOpPackageName()); 86 } catch (RemoteException e) { 87 throw e.rethrowFromSystemServer(); 88 } 89 } 90 91 /** 92 * Return the total size of the underlying physical media that is hosting 93 * this storage volume. 94 * <p> 95 * This value is best suited for visual display to end users, since it's 96 * designed to reflect the total storage size advertised in a retail 97 * environment. 98 * <p> 99 * Apps making logical decisions about disk space should always use 100 * {@link File#getTotalSpace()} instead of this value. 101 * 102 * @param storageUuid the UUID of the storage volume you're interested in, 103 * such as {@link StorageManager#UUID_DEFAULT}. 104 * @throws IOException when the storage device isn't present. 105 */ 106 @WorkerThread getTotalBytes(@onNull UUID storageUuid)107 public @BytesLong long getTotalBytes(@NonNull UUID storageUuid) throws IOException { 108 try { 109 return mService.getTotalBytes(convert(storageUuid), mContext.getOpPackageName()); 110 } catch (ParcelableException e) { 111 e.maybeRethrow(IOException.class); 112 throw new RuntimeException(e); 113 } catch (RemoteException e) { 114 throw e.rethrowFromSystemServer(); 115 } 116 } 117 118 /** @removed */ 119 @Deprecated getTotalBytes(String uuid)120 public long getTotalBytes(String uuid) throws IOException { 121 return getTotalBytes(convert(uuid)); 122 } 123 124 /** 125 * Return the free space on the requested storage volume. 126 * <p> 127 * This value is best suited for visual display to end users, since it's 128 * designed to reflect both unused space <em>and</em> and cached space that 129 * could be reclaimed by the system. 130 * <p> 131 * Apps making logical decisions about disk space should always use 132 * {@link StorageManager#getAllocatableBytes(UUID)} instead of this value. 133 * 134 * @param storageUuid the UUID of the storage volume you're interested in, 135 * such as {@link StorageManager#UUID_DEFAULT}. 136 * @throws IOException when the storage device isn't present. 137 */ 138 @WorkerThread getFreeBytes(@onNull UUID storageUuid)139 public @BytesLong long getFreeBytes(@NonNull UUID storageUuid) throws IOException { 140 try { 141 return mService.getFreeBytes(convert(storageUuid), mContext.getOpPackageName()); 142 } catch (ParcelableException e) { 143 e.maybeRethrow(IOException.class); 144 throw new RuntimeException(e); 145 } catch (RemoteException e) { 146 throw e.rethrowFromSystemServer(); 147 } 148 } 149 150 /** @removed */ 151 @Deprecated getFreeBytes(String uuid)152 public long getFreeBytes(String uuid) throws IOException { 153 return getFreeBytes(convert(uuid)); 154 } 155 156 /** {@hide} */ getCacheBytes(@onNull UUID storageUuid)157 public @BytesLong long getCacheBytes(@NonNull UUID storageUuid) throws IOException { 158 try { 159 return mService.getCacheBytes(convert(storageUuid), mContext.getOpPackageName()); 160 } catch (ParcelableException e) { 161 e.maybeRethrow(IOException.class); 162 throw new RuntimeException(e); 163 } catch (RemoteException e) { 164 throw e.rethrowFromSystemServer(); 165 } 166 } 167 168 /** {@hide} */ 169 @Deprecated getCacheBytes(String uuid)170 public long getCacheBytes(String uuid) throws IOException { 171 return getCacheBytes(convert(uuid)); 172 } 173 174 /** 175 * Return storage statistics for a specific package on the requested storage 176 * volume. 177 * <p class="note"> 178 * Note: no permissions are required when calling this API for your own 179 * package. However, requesting details for any other package requires the 180 * {@code android.Manifest.permission#PACKAGE_USAGE_STATS} permission, which 181 * is a system-level permission that will not be granted to normal apps. 182 * Declaring that permission expresses your intention to use this API and an 183 * end user can then choose to grant this permission through the Settings 184 * application. 185 * </p> 186 * <p class="note"> 187 * Note: if the requested package uses the {@code android:sharedUserId} 188 * manifest feature, this call will be forced into a slower manual 189 * calculation path. If possible, consider always using 190 * {@link #queryStatsForUid(UUID, int)}, which is typically faster. 191 * </p> 192 * 193 * @param storageUuid the UUID of the storage volume you're interested in, 194 * such as {@link StorageManager#UUID_DEFAULT}. 195 * @param packageName the package name you're interested in. 196 * @param user the user you're interested in. 197 * @throws PackageManager.NameNotFoundException when the requested package 198 * name isn't installed for the requested user. 199 * @throws IOException when the storage device isn't present. 200 * @see ApplicationInfo#storageUuid 201 * @see PackageInfo#packageName 202 */ 203 @WorkerThread queryStatsForPackage(@onNull UUID storageUuid, @NonNull String packageName, @NonNull UserHandle user)204 public @NonNull StorageStats queryStatsForPackage(@NonNull UUID storageUuid, 205 @NonNull String packageName, @NonNull UserHandle user) 206 throws PackageManager.NameNotFoundException, IOException { 207 try { 208 return mService.queryStatsForPackage(convert(storageUuid), packageName, 209 user.getIdentifier(), mContext.getOpPackageName()); 210 } catch (ParcelableException e) { 211 e.maybeRethrow(PackageManager.NameNotFoundException.class); 212 e.maybeRethrow(IOException.class); 213 throw new RuntimeException(e); 214 } catch (RemoteException e) { 215 throw e.rethrowFromSystemServer(); 216 } 217 } 218 219 /** @removed */ 220 @Deprecated queryStatsForPackage(String uuid, String packageName, UserHandle user)221 public StorageStats queryStatsForPackage(String uuid, String packageName, 222 UserHandle user) throws PackageManager.NameNotFoundException, IOException { 223 return queryStatsForPackage(convert(uuid), packageName, user); 224 } 225 226 /** 227 * Return storage statistics for a specific UID on the requested storage 228 * volume. 229 * <p class="note"> 230 * Note: no permissions are required when calling this API for your own UID. 231 * However, requesting details for any other UID requires the 232 * {@code android.Manifest.permission#PACKAGE_USAGE_STATS} permission, which 233 * is a system-level permission that will not be granted to normal apps. 234 * Declaring that permission expresses your intention to use this API and an 235 * end user can then choose to grant this permission through the Settings 236 * application. 237 * </p> 238 * 239 * @param storageUuid the UUID of the storage volume you're interested in, 240 * such as {@link StorageManager#UUID_DEFAULT}. 241 * @param uid the UID you're interested in. 242 * @throws IOException when the storage device isn't present. 243 * @see ApplicationInfo#storageUuid 244 * @see ApplicationInfo#uid 245 */ 246 @WorkerThread queryStatsForUid(@onNull UUID storageUuid, int uid)247 public @NonNull StorageStats queryStatsForUid(@NonNull UUID storageUuid, int uid) 248 throws IOException { 249 try { 250 return mService.queryStatsForUid(convert(storageUuid), uid, 251 mContext.getOpPackageName()); 252 } catch (ParcelableException e) { 253 e.maybeRethrow(IOException.class); 254 throw new RuntimeException(e); 255 } catch (RemoteException e) { 256 throw e.rethrowFromSystemServer(); 257 } 258 } 259 260 /** @removed */ 261 @Deprecated queryStatsForUid(String uuid, int uid)262 public StorageStats queryStatsForUid(String uuid, int uid) throws IOException { 263 return queryStatsForUid(convert(uuid), uid); 264 } 265 266 /** 267 * Return storage statistics for a specific {@link UserHandle} on the 268 * requested storage volume. 269 * <p class="note"> 270 * Note: this API requires the 271 * {@code android.Manifest.permission#PACKAGE_USAGE_STATS} permission, which 272 * is a system-level permission that will not be granted to normal apps. 273 * Declaring that permission expresses your intention to use this API and an 274 * end user can then choose to grant this permission through the Settings 275 * application. 276 * </p> 277 * 278 * @param storageUuid the UUID of the storage volume you're interested in, 279 * such as {@link StorageManager#UUID_DEFAULT}. 280 * @param user the user you're interested in. 281 * @throws IOException when the storage device isn't present. 282 * @see android.os.Process#myUserHandle() 283 */ 284 @WorkerThread queryStatsForUser(@onNull UUID storageUuid, @NonNull UserHandle user)285 public @NonNull StorageStats queryStatsForUser(@NonNull UUID storageUuid, 286 @NonNull UserHandle user) throws IOException { 287 try { 288 return mService.queryStatsForUser(convert(storageUuid), user.getIdentifier(), 289 mContext.getOpPackageName()); 290 } catch (ParcelableException e) { 291 e.maybeRethrow(IOException.class); 292 throw new RuntimeException(e); 293 } catch (RemoteException e) { 294 throw e.rethrowFromSystemServer(); 295 } 296 } 297 298 /** @removed */ 299 @Deprecated queryStatsForUser(String uuid, UserHandle user)300 public StorageStats queryStatsForUser(String uuid, UserHandle user) throws IOException { 301 return queryStatsForUser(convert(uuid), user); 302 } 303 304 /** 305 * Return shared/external storage statistics for a specific 306 * {@link UserHandle} on the requested storage volume. 307 * <p class="note"> 308 * Note: this API requires the 309 * {@code android.Manifest.permission#PACKAGE_USAGE_STATS} permission, which 310 * is a system-level permission that will not be granted to normal apps. 311 * Declaring that permission expresses your intention to use this API and an 312 * end user can then choose to grant this permission through the Settings 313 * application. 314 * </p> 315 * 316 * @param storageUuid the UUID of the storage volume you're interested in, 317 * such as {@link StorageManager#UUID_DEFAULT}. 318 * @throws IOException when the storage device isn't present. 319 * @see android.os.Process#myUserHandle() 320 */ 321 @WorkerThread queryExternalStatsForUser(@onNull UUID storageUuid, @NonNull UserHandle user)322 public @NonNull ExternalStorageStats queryExternalStatsForUser(@NonNull UUID storageUuid, 323 @NonNull UserHandle user) throws IOException { 324 try { 325 return mService.queryExternalStatsForUser(convert(storageUuid), user.getIdentifier(), 326 mContext.getOpPackageName()); 327 } catch (ParcelableException e) { 328 e.maybeRethrow(IOException.class); 329 throw new RuntimeException(e); 330 } catch (RemoteException e) { 331 throw e.rethrowFromSystemServer(); 332 } 333 } 334 335 /** @removed */ 336 @Deprecated queryExternalStatsForUser(String uuid, UserHandle user)337 public ExternalStorageStats queryExternalStatsForUser(String uuid, UserHandle user) 338 throws IOException { 339 return queryExternalStatsForUser(convert(uuid), user); 340 } 341 342 /** {@hide} */ getCacheQuotaBytes(String volumeUuid, int uid)343 public long getCacheQuotaBytes(String volumeUuid, int uid) { 344 try { 345 return mService.getCacheQuotaBytes(volumeUuid, uid, mContext.getOpPackageName()); 346 } catch (RemoteException e) { 347 throw e.rethrowFromSystemServer(); 348 } 349 } 350 } 351