/*
 * Copyright (C) 2011 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 com.android.settingslib.deviceinfo;

import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageStatsObserver;
import android.content.pm.PackageManager;
import android.content.pm.PackageStats;
import android.content.pm.UserInfo;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.StorageVolume;
import android.os.storage.VolumeInfo;
import android.util.Log;
import android.util.SparseLongArray;

import com.android.internal.app.IMediaContainerService;
import com.android.internal.util.ArrayUtils;
import com.google.android.collect.Sets;

import java.io.File;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * Utility for measuring the disk usage of internal storage or a physical
 * {@link StorageVolume}. Connects with a remote {@link IMediaContainerService}
 * and delivers results to {@link MeasurementReceiver}.
 */
public class StorageMeasurement {
    private static final String TAG = "StorageMeasurement";

    private static final boolean LOCAL_LOGV = true;
    static final boolean LOGV = LOCAL_LOGV && Log.isLoggable(TAG, Log.VERBOSE);

    private static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer";

    public static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
            DEFAULT_CONTAINER_PACKAGE, "com.android.defcontainer.DefaultContainerService");

    /** Media types to measure on external storage. */
    private static final Set<String> sMeasureMediaTypes = Sets.newHashSet(
            Environment.DIRECTORY_DCIM, Environment.DIRECTORY_MOVIES,
            Environment.DIRECTORY_PICTURES, Environment.DIRECTORY_MUSIC,
            Environment.DIRECTORY_ALARMS, Environment.DIRECTORY_NOTIFICATIONS,
            Environment.DIRECTORY_RINGTONES, Environment.DIRECTORY_PODCASTS,
            Environment.DIRECTORY_DOWNLOADS, Environment.DIRECTORY_ANDROID);

    public static class MeasurementDetails {
        /**
         * Total apps disk usage.
         * <p>
         * When measuring internal storage, this value includes the code size of
         * all apps (regardless of install status for current user), and
         * internal disk used by the current user's apps. When the device
         * emulates external storage, this value also includes emulated storage
         * used by the current user's apps.
         * <p>
         * When measuring a physical {@link StorageVolume}, this value includes
         * usage by all apps on that volume.
         */
        public long appsSize;

        /**
         * Total cache disk usage by apps.
         */
        public long cacheSize;

        /**
         * Total media disk usage, categorized by types such as
         * {@link Environment#DIRECTORY_MUSIC}.
         * <p>
         * When measuring internal storage, this reflects media on emulated
         * storage for the current user.
         * <p>
         * When measuring a physical {@link StorageVolume}, this reflects media
         * on that volume.
         */
        public HashMap<String, Long> mediaSize = new HashMap<>();

        /**
         * Misc external disk usage for the current user, unaccounted in
         * {@link #mediaSize}.
         */
        public long miscSize;

        /**
         * Total disk usage for users, which is only meaningful for emulated
         * internal storage. Key is {@link UserHandle}.
         */
        public SparseLongArray usersSize = new SparseLongArray();
    }

    public interface MeasurementReceiver {
        public void onDetailsChanged(MeasurementDetails details);
    }

    private WeakReference<MeasurementReceiver> mReceiver;

    private final Context mContext;

    private final VolumeInfo mVolume;
    private final VolumeInfo mSharedVolume;

    private final MainHandler mMainHandler;
    private final MeasurementHandler mMeasurementHandler;

    public StorageMeasurement(Context context, VolumeInfo volume, VolumeInfo sharedVolume) {
        mContext = context.getApplicationContext();

        mVolume = volume;
        mSharedVolume = sharedVolume;

        // Start the thread that will measure the disk usage.
        final HandlerThread handlerThread = new HandlerThread("MemoryMeasurement");
        handlerThread.start();

        mMainHandler = new MainHandler();
        mMeasurementHandler = new MeasurementHandler(handlerThread.getLooper());
    }

    public void setReceiver(MeasurementReceiver receiver) {
        if (mReceiver == null || mReceiver.get() == null) {
            mReceiver = new WeakReference<MeasurementReceiver>(receiver);
        }
    }

    public void forceMeasure() {
        invalidate();
        measure();
    }

    public void measure() {
        if (!mMeasurementHandler.hasMessages(MeasurementHandler.MSG_MEASURE)) {
            mMeasurementHandler.sendEmptyMessage(MeasurementHandler.MSG_MEASURE);
        }
    }

    public void onDestroy() {
        mReceiver = null;
        mMeasurementHandler.removeMessages(MeasurementHandler.MSG_MEASURE);
        mMeasurementHandler.sendEmptyMessage(MeasurementHandler.MSG_DISCONNECT);
    }

    private void invalidate() {
        mMeasurementHandler.sendEmptyMessage(MeasurementHandler.MSG_INVALIDATE);
    }

    private static class StatsObserver extends IPackageStatsObserver.Stub {
        private final boolean mIsPrivate;
        private final MeasurementDetails mDetails;
        private final int mCurrentUser;
        private final Message mFinished;

        private int mRemaining;

        public StatsObserver(boolean isPrivate, MeasurementDetails details, int currentUser,
                Message finished, int remaining) {
            mIsPrivate = isPrivate;
            mDetails = details;
            mCurrentUser = currentUser;
            mFinished = finished;
            mRemaining = remaining;
        }

        @Override
        public void onGetStatsCompleted(PackageStats stats, boolean succeeded) {
            synchronized (mDetails) {
                if (succeeded) {
                    addStatsLocked(stats);
                }
                if (--mRemaining == 0) {
                    mFinished.sendToTarget();
                }
            }
        }

        private void addStatsLocked(PackageStats stats) {
            if (mIsPrivate) {
                long codeSize = stats.codeSize;
                long dataSize = stats.dataSize;
                long cacheSize = stats.cacheSize;
                if (Environment.isExternalStorageEmulated()) {
                    // Include emulated storage when measuring internal. OBB is
                    // shared on emulated storage, so treat as code.
                    codeSize += stats.externalCodeSize + stats.externalObbSize;
                    dataSize += stats.externalDataSize + stats.externalMediaSize;
                    cacheSize += stats.externalCacheSize;
                }

                // Count code and data for current user
                if (stats.userHandle == mCurrentUser) {
                    mDetails.appsSize += codeSize;
                    mDetails.appsSize += dataSize;
                }

                // User summary only includes data (code is only counted once
                // for the current user)
                addValue(mDetails.usersSize, stats.userHandle, dataSize);

                // Include cache for all users
                mDetails.cacheSize += cacheSize;

            } else {
                // Physical storage; only count external sizes
                mDetails.appsSize += stats.externalCodeSize + stats.externalDataSize
                        + stats.externalMediaSize + stats.externalObbSize;
                mDetails.cacheSize += stats.externalCacheSize;
            }
        }
    }

    private class MainHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            final MeasurementDetails details = (MeasurementDetails) msg.obj;
            final MeasurementReceiver receiver = (mReceiver != null) ? mReceiver.get() : null;
            if (receiver != null) {
                receiver.onDetailsChanged(details);
            }
        }
    }

    private class MeasurementHandler extends Handler {
        public static final int MSG_MEASURE = 1;
        public static final int MSG_CONNECTED = 2;
        public static final int MSG_DISCONNECT = 3;
        public static final int MSG_COMPLETED = 4;
        public static final int MSG_INVALIDATE = 5;

        private Object mLock = new Object();

        private IMediaContainerService mDefaultContainer;

        private volatile boolean mBound = false;

        private MeasurementDetails mCached;

        private final ServiceConnection mDefContainerConn = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                final IMediaContainerService imcs = IMediaContainerService.Stub.asInterface(
                        service);
                mDefaultContainer = imcs;
                mBound = true;
                sendMessage(obtainMessage(MSG_CONNECTED, imcs));
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                mBound = false;
                removeMessages(MSG_CONNECTED);
            }
        };

        public MeasurementHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_MEASURE: {
                    if (mCached != null) {
                        mMainHandler.obtainMessage(0, mCached).sendToTarget();
                        break;
                    }

                    synchronized (mLock) {
                        if (mBound) {
                            removeMessages(MSG_DISCONNECT);
                            sendMessage(obtainMessage(MSG_CONNECTED, mDefaultContainer));
                        } else {
                            Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
                            mContext.bindServiceAsUser(service, mDefContainerConn,
                                    Context.BIND_AUTO_CREATE, UserHandle.OWNER);
                        }
                    }
                    break;
                }
                case MSG_CONNECTED: {
                    final IMediaContainerService imcs = (IMediaContainerService) msg.obj;
                    measureExactStorage(imcs);
                    break;
                }
                case MSG_DISCONNECT: {
                    synchronized (mLock) {
                        if (mBound) {
                            mBound = false;
                            mContext.unbindService(mDefContainerConn);
                        }
                    }
                    break;
                }
                case MSG_COMPLETED: {
                    mCached = (MeasurementDetails) msg.obj;
                    mMainHandler.obtainMessage(0, mCached).sendToTarget();
                    break;
                }
                case MSG_INVALIDATE: {
                    mCached = null;
                    break;
                }
            }
        }
    }

    private void measureExactStorage(IMediaContainerService imcs) {
        final UserManager userManager = mContext.getSystemService(UserManager.class);
        final PackageManager packageManager = mContext.getPackageManager();

        final List<UserInfo> users = userManager.getUsers();
        final int currentUser = ActivityManager.getCurrentUser();

        final MeasurementDetails details = new MeasurementDetails();
        final Message finished = mMeasurementHandler.obtainMessage(MeasurementHandler.MSG_COMPLETED,
                details);

        if (mSharedVolume != null && mSharedVolume.isMountedReadable()) {
            final File basePath = mSharedVolume.getPathForUser(currentUser);

            // Measure media types for emulated storage, or for primary physical
            // external volume
            for (String type : sMeasureMediaTypes) {
                final File path = new File(basePath, type);
                final long size = getDirectorySize(imcs, path);
                details.mediaSize.put(type, size);
            }

            // Measure misc files not counted under media
            details.miscSize = measureMisc(imcs, basePath);

            if (mSharedVolume.getType() == VolumeInfo.TYPE_EMULATED) {
                // Measure total emulated storage of all users; internal apps data
                // will be spliced in later
                for (UserInfo user : users) {
                    final File userPath = mSharedVolume.getPathForUser(user.id);
                    final long size = getDirectorySize(imcs, userPath);
                    addValue(details.usersSize, user.id, size);
                }
            }
        }

        // Measure all apps hosted on this volume for all users
        if (mVolume.getType() == VolumeInfo.TYPE_PRIVATE) {
            final List<ApplicationInfo> apps = packageManager.getInstalledApplications(
                    PackageManager.GET_UNINSTALLED_PACKAGES
                    | PackageManager.GET_DISABLED_COMPONENTS);

            final List<ApplicationInfo> volumeApps = new ArrayList<>();
            for (ApplicationInfo app : apps) {
                if (Objects.equals(app.volumeUuid, mVolume.getFsUuid())) {
                    volumeApps.add(app);
                }
            }

            final int count = users.size() * volumeApps.size();
            if (count == 0) {
                finished.sendToTarget();
                return;
            }

            final StatsObserver observer = new StatsObserver(
                    true, details, currentUser, finished, count);
            for (UserInfo user : users) {
                for (ApplicationInfo app : volumeApps) {
                    packageManager.getPackageSizeInfo(app.packageName, user.id, observer);
                }
            }

        } else {
            finished.sendToTarget();
            return;
        }
    }

    private static long getDirectorySize(IMediaContainerService imcs, File path) {
        try {
            final long size = imcs.calculateDirectorySize(path.toString());
            Log.d(TAG, "getDirectorySize(" + path + ") returned " + size);
            return size;
        } catch (Exception e) {
            Log.w(TAG, "Could not read memory from default container service for " + path, e);
            return 0;
        }
    }

    private long measureMisc(IMediaContainerService imcs, File dir) {
        final File[] files = dir.listFiles();
        if (ArrayUtils.isEmpty(files)) return 0;

        // Get sizes of all top level nodes except the ones already computed
        long miscSize = 0;
        for (File file : files) {
            final String name = file.getName();
            if (sMeasureMediaTypes.contains(name)) {
                continue;
            }

            if (file.isFile()) {
                miscSize += file.length();
            } else if (file.isDirectory()) {
                miscSize += getDirectorySize(imcs, file);
            }
        }
        return miscSize;
    }

    private static void addValue(SparseLongArray array, int key, long value) {
        array.put(key, array.get(key) + value);
    }
}
