/*
 * 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.RequiresPermission;
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.content.pm.ParceledListSlice;
import android.os.ParcelableException;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.storage.CrateInfo;
import android.os.storage.StorageManager;

import com.android.internal.util.Preconditions;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Objects;
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.
 * <p class="note">
 * 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.
 * </p>
 */
@SystemService(Context.STORAGE_STATS_SERVICE)
public class StorageStatsManager {
    private final Context mContext;
    private final IStorageStatsManager mService;

    /** {@hide} */
    public StorageStatsManager(Context context, IStorageStatsManager service) {
        mContext = Objects.requireNonNull(context);
        mService = Objects.requireNonNull(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));
    }

    /** {@hide} */
    @TestApi
    public boolean isReservedSupported(@NonNull UUID storageUuid) {
        try {
            return mService.isReservedSupported(convert(storageUuid), mContext.getOpPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Return the total size of the underlying physical media that is hosting
     * this storage volume.
     * <p>
     * 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.
     * <p>
     * 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.
     * <p>
     * This value is best suited for visual display to end users, since it's
     * designed to reflect both unused space <em>and</em> and cached space that
     * could be reclaimed by the system.
     * <p>
     * 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.
     * <p class="note">
     * 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.
     * </p>
     * <p class="note">
     * 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.
     * </p>
     *
     * @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.
     * <p class="note">
     * 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.
     * </p>
     *
     * @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.
     * <p class="note">
     * 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.
     * </p>
     *
     * @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.
     * <p class="note">
     * 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.
     * </p>
     *
     * @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();
        }
    }

    /**
     * Return all of crate information for the specified storageUuid, packageName, and
     * userHandle.
     *
     * @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.
     * @return the collection of crate information.
     * @throws PackageManager.NameNotFoundException when the package name is not found.
     * @throws IOException cause by IO, not support, or the other reasons.
     * @hide
     */
    @TestApi
    @WorkerThread
    @NonNull
    public Collection<CrateInfo> queryCratesForUid(@NonNull UUID storageUuid,
            int uid) throws IOException, PackageManager.NameNotFoundException {
        try {
            ParceledListSlice<CrateInfo> crateInfoList =
                    mService.queryCratesForUid(convert(storageUuid), uid,
                            mContext.getOpPackageName());
            return Objects.requireNonNull(crateInfoList).getList();
        } catch (ParcelableException e) {
            e.maybeRethrow(PackageManager.NameNotFoundException.class);
            e.maybeRethrow(IOException.class);
            throw new RuntimeException(e);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Return all of crates information for the specified storageUuid, packageName, and
     * userHandle.
     *
     * @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.
     * @return the collection of crate information.
     * @throws PackageManager.NameNotFoundException when the package name is not found.
     * @throws IOException cause by IO, not support, or the other reasons.
     * @hide
     */
    @WorkerThread
    @TestApi
    @NonNull
    public Collection<CrateInfo> queryCratesForPackage(@NonNull UUID storageUuid,
            @NonNull String packageName, @NonNull UserHandle user)
            throws PackageManager.NameNotFoundException, IOException {
        try {
            ParceledListSlice<CrateInfo> crateInfoList =
                    mService.queryCratesForPackage(convert(storageUuid), packageName,
                            user.getIdentifier(), mContext.getOpPackageName());
            return Objects.requireNonNull(crateInfoList).getList();
        } catch (ParcelableException e) {
            e.maybeRethrow(PackageManager.NameNotFoundException.class);
            e.maybeRethrow(IOException.class);
            throw new RuntimeException(e);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Return all of crate information for the specified storageUuid, packageName, and
     * userHandle.
     *
     * @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.
     * @return the collection of crate information.
     * @throws PackageManager.NameNotFoundException when the package name is not found.
     * @throws IOException cause by IO, not support, or the other reasons.
     * @hide
     */
    @WorkerThread
    @TestApi
    @RequiresPermission(android.Manifest.permission.MANAGE_CRATES)
    @NonNull
    public Collection<CrateInfo> queryCratesForUser(@NonNull UUID storageUuid,
            @NonNull UserHandle user) throws PackageManager.NameNotFoundException, IOException {
        try {
            ParceledListSlice<CrateInfo> crateInfoList =
                    mService.queryCratesForUser(convert(storageUuid), user.getIdentifier(),
                            mContext.getOpPackageName());
            return Objects.requireNonNull(crateInfoList).getList();
        } catch (ParcelableException e) {
            e.maybeRethrow(PackageManager.NameNotFoundException.class);
            e.maybeRethrow(IOException.class);
            throw new RuntimeException(e);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
}
