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

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