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