/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.app.usage; import static android.os.storage.StorageManager.convert; import android.annotation.BytesLong; import android.annotation.NonNull; import android.annotation.SystemService; import android.annotation.TestApi; import android.annotation.WorkerThread; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.os.ParcelableException; import android.os.RemoteException; import android.os.UserHandle; import android.os.storage.StorageManager; import com.android.internal.util.Preconditions; import java.io.File; import java.io.IOException; import java.util.UUID; /** * Access to detailed storage statistics. This provides a summary of how apps, * users, and external/shared storage is utilizing disk space. *

* Note: no permissions are required when calling these APIs for your own * package or UID. However, requesting details for any other package requires * the {@code android.Manifest.permission#PACKAGE_USAGE_STATS} permission, which * is a system-level permission that will not be granted to normal apps. * Declaring that permission expresses your intention to use this API and an end * user can then choose to grant this permission through the Settings * application. *

*/ @SystemService(Context.STORAGE_STATS_SERVICE) public class StorageStatsManager { private final Context mContext; private final IStorageStatsManager mService; /** {@hide} */ public StorageStatsManager(Context context, IStorageStatsManager service) { mContext = Preconditions.checkNotNull(context); mService = Preconditions.checkNotNull(service); } /** {@hide} */ @TestApi public boolean isQuotaSupported(@NonNull UUID storageUuid) { try { return mService.isQuotaSupported(convert(storageUuid), mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** @removed */ @Deprecated public boolean isQuotaSupported(String uuid) { return isQuotaSupported(convert(uuid)); } /** * Return the total size of the underlying physical media that is hosting * this storage volume. *

* This value is best suited for visual display to end users, since it's * designed to reflect the total storage size advertised in a retail * environment. *

* Apps making logical decisions about disk space should always use * {@link File#getTotalSpace()} instead of this value. * * @param storageUuid the UUID of the storage volume you're interested in, * such as {@link StorageManager#UUID_DEFAULT}. * @throws IOException when the storage device isn't present. */ @WorkerThread public @BytesLong long getTotalBytes(@NonNull UUID storageUuid) throws IOException { try { return mService.getTotalBytes(convert(storageUuid), mContext.getOpPackageName()); } catch (ParcelableException e) { e.maybeRethrow(IOException.class); throw new RuntimeException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** @removed */ @Deprecated public long getTotalBytes(String uuid) throws IOException { return getTotalBytes(convert(uuid)); } /** * Return the free space on the requested storage volume. *

* This value is best suited for visual display to end users, since it's * designed to reflect both unused space and and cached space that * could be reclaimed by the system. *

* Apps making logical decisions about disk space should always use * {@link StorageManager#getAllocatableBytes(UUID)} instead of this value. * * @param storageUuid the UUID of the storage volume you're interested in, * such as {@link StorageManager#UUID_DEFAULT}. * @throws IOException when the storage device isn't present. */ @WorkerThread public @BytesLong long getFreeBytes(@NonNull UUID storageUuid) throws IOException { try { return mService.getFreeBytes(convert(storageUuid), mContext.getOpPackageName()); } catch (ParcelableException e) { e.maybeRethrow(IOException.class); throw new RuntimeException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** @removed */ @Deprecated public long getFreeBytes(String uuid) throws IOException { return getFreeBytes(convert(uuid)); } /** {@hide} */ public @BytesLong long getCacheBytes(@NonNull UUID storageUuid) throws IOException { try { return mService.getCacheBytes(convert(storageUuid), mContext.getOpPackageName()); } catch (ParcelableException e) { e.maybeRethrow(IOException.class); throw new RuntimeException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** {@hide} */ @Deprecated public long getCacheBytes(String uuid) throws IOException { return getCacheBytes(convert(uuid)); } /** * Return storage statistics for a specific package on the requested storage * volume. *

* Note: no permissions are required when calling this API for your own * package. However, requesting details for any other package requires the * {@code android.Manifest.permission#PACKAGE_USAGE_STATS} permission, which * is a system-level permission that will not be granted to normal apps. * Declaring that permission expresses your intention to use this API and an * end user can then choose to grant this permission through the Settings * application. *

*

* Note: if the requested package uses the {@code android:sharedUserId} * manifest feature, this call will be forced into a slower manual * calculation path. If possible, consider always using * {@link #queryStatsForUid(UUID, int)}, which is typically faster. *

* * @param storageUuid the UUID of the storage volume you're interested in, * such as {@link StorageManager#UUID_DEFAULT}. * @param packageName the package name you're interested in. * @param user the user you're interested in. * @throws PackageManager.NameNotFoundException when the requested package * name isn't installed for the requested user. * @throws IOException when the storage device isn't present. * @see ApplicationInfo#storageUuid * @see PackageInfo#packageName */ @WorkerThread public @NonNull StorageStats queryStatsForPackage(@NonNull UUID storageUuid, @NonNull String packageName, @NonNull UserHandle user) throws PackageManager.NameNotFoundException, IOException { try { return mService.queryStatsForPackage(convert(storageUuid), packageName, user.getIdentifier(), mContext.getOpPackageName()); } catch (ParcelableException e) { e.maybeRethrow(PackageManager.NameNotFoundException.class); e.maybeRethrow(IOException.class); throw new RuntimeException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** @removed */ @Deprecated public StorageStats queryStatsForPackage(String uuid, String packageName, UserHandle user) throws PackageManager.NameNotFoundException, IOException { return queryStatsForPackage(convert(uuid), packageName, user); } /** * Return storage statistics for a specific UID on the requested storage * volume. *

* Note: no permissions are required when calling this API for your own UID. * However, requesting details for any other UID requires the * {@code android.Manifest.permission#PACKAGE_USAGE_STATS} permission, which * is a system-level permission that will not be granted to normal apps. * Declaring that permission expresses your intention to use this API and an * end user can then choose to grant this permission through the Settings * application. *

* * @param storageUuid the UUID of the storage volume you're interested in, * such as {@link StorageManager#UUID_DEFAULT}. * @param uid the UID you're interested in. * @throws IOException when the storage device isn't present. * @see ApplicationInfo#storageUuid * @see ApplicationInfo#uid */ @WorkerThread public @NonNull StorageStats queryStatsForUid(@NonNull UUID storageUuid, int uid) throws IOException { try { return mService.queryStatsForUid(convert(storageUuid), uid, mContext.getOpPackageName()); } catch (ParcelableException e) { e.maybeRethrow(IOException.class); throw new RuntimeException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** @removed */ @Deprecated public StorageStats queryStatsForUid(String uuid, int uid) throws IOException { return queryStatsForUid(convert(uuid), uid); } /** * Return storage statistics for a specific {@link UserHandle} on the * requested storage volume. *

* Note: this API requires the * {@code android.Manifest.permission#PACKAGE_USAGE_STATS} permission, which * is a system-level permission that will not be granted to normal apps. * Declaring that permission expresses your intention to use this API and an * end user can then choose to grant this permission through the Settings * application. *

* * @param storageUuid the UUID of the storage volume you're interested in, * such as {@link StorageManager#UUID_DEFAULT}. * @param user the user you're interested in. * @throws IOException when the storage device isn't present. * @see android.os.Process#myUserHandle() */ @WorkerThread public @NonNull StorageStats queryStatsForUser(@NonNull UUID storageUuid, @NonNull UserHandle user) throws IOException { try { return mService.queryStatsForUser(convert(storageUuid), user.getIdentifier(), mContext.getOpPackageName()); } catch (ParcelableException e) { e.maybeRethrow(IOException.class); throw new RuntimeException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** @removed */ @Deprecated public StorageStats queryStatsForUser(String uuid, UserHandle user) throws IOException { return queryStatsForUser(convert(uuid), user); } /** * Return shared/external storage statistics for a specific * {@link UserHandle} on the requested storage volume. *

* Note: this API requires the * {@code android.Manifest.permission#PACKAGE_USAGE_STATS} permission, which * is a system-level permission that will not be granted to normal apps. * Declaring that permission expresses your intention to use this API and an * end user can then choose to grant this permission through the Settings * application. *

* * @param storageUuid the UUID of the storage volume you're interested in, * such as {@link StorageManager#UUID_DEFAULT}. * @throws IOException when the storage device isn't present. * @see android.os.Process#myUserHandle() */ @WorkerThread public @NonNull ExternalStorageStats queryExternalStatsForUser(@NonNull UUID storageUuid, @NonNull UserHandle user) throws IOException { try { return mService.queryExternalStatsForUser(convert(storageUuid), user.getIdentifier(), mContext.getOpPackageName()); } catch (ParcelableException e) { e.maybeRethrow(IOException.class); throw new RuntimeException(e); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** @removed */ @Deprecated public ExternalStorageStats queryExternalStatsForUser(String uuid, UserHandle user) throws IOException { return queryExternalStatsForUser(convert(uuid), user); } /** {@hide} */ public long getCacheQuotaBytes(String volumeUuid, int uid) { try { return mService.getCacheQuotaBytes(volumeUuid, uid, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } }