Home | History | Annotate | Download | only in usage
      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