/*
 * 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.
 * <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 = 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));
    }

    /** {@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();
        }
    }
}
