/*
 * Copyright (C) 2016 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/LICENSE2.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.server.storage;

import android.app.job.JobInfo;
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
import android.app.job.JobService;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageStats;
import android.os.AsyncTask;
import android.os.BatteryManager;
import android.os.Environment;
import android.os.Environment.UserEnvironment;
import android.os.UserHandle;
import android.os.storage.VolumeInfo;
import android.provider.Settings;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.storage.FileCollector.MeasurementResult;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * DiskStatsLoggingService is a JobService which collects storage categorization information and
 * app size information on a roughly daily cadence.
 */
public class DiskStatsLoggingService extends JobService {
    private static final String TAG = "DiskStatsLogService";
    public static final String DUMPSYS_CACHE_PATH = "/data/system/diskstats_cache.json";
    private static final int JOB_DISKSTATS_LOGGING = 0x4449534b; // DISK
    private static ComponentName sDiskStatsLoggingService = new ComponentName(
            "android",
            DiskStatsLoggingService.class.getName());

    @Override
    public boolean onStartJob(JobParameters params) {
        // We need to check the preconditions again because they may not be enforced for
        // subsequent runs.
        if (!isCharging(this) || !isDumpsysTaskEnabled(getContentResolver())) {
            jobFinished(params, true);
            return false;
        }


        VolumeInfo volume = getPackageManager().getPrimaryStorageCurrentVolume();
        // volume is null if the primary storage is not yet mounted.
        if (volume == null) {
            return false;
        }
        AppCollector collector = new AppCollector(this, volume);

        final int userId = UserHandle.myUserId();
        UserEnvironment environment = new UserEnvironment(userId);
        LogRunnable task = new LogRunnable();
        task.setDownloadsDirectory(
                environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS));
        task.setSystemSize(FileCollector.getSystemSize(this));
        task.setLogOutputFile(new File(DUMPSYS_CACHE_PATH));
        task.setAppCollector(collector);
        task.setJobService(this, params);
        task.setContext(this);
        AsyncTask.execute(task);
        return true;
    }

    @Override
    public boolean onStopJob(JobParameters params) {
        // TODO: Try to stop being handled.
        return false;
    }

    /**
     * Schedules a DiskStats collection task. This task only runs on device idle while charging
     * once every 24 hours.
     * @param context Context to use to get a job scheduler.
     */
    public static void schedule(Context context) {
        JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);

        js.schedule(new JobInfo.Builder(JOB_DISKSTATS_LOGGING, sDiskStatsLoggingService)
                .setRequiresDeviceIdle(true)
                .setRequiresCharging(true)
                .setPeriodic(TimeUnit.DAYS.toMillis(1))
                .build());
    }

    private static boolean isCharging(Context context) {
        BatteryManager batteryManager =
                (BatteryManager) context.getSystemService(Context.BATTERY_SERVICE);
        if (batteryManager != null) {
            return batteryManager.isCharging();
        }
        return false;
    }

    @VisibleForTesting
    static boolean isDumpsysTaskEnabled(ContentResolver resolver) {
        // The default is to treat the task as enabled.
        return Settings.Global.getInt(resolver, Settings.Global.ENABLE_DISKSTATS_LOGGING, 1) != 0;
    }

    @VisibleForTesting
    static class LogRunnable implements Runnable {
        private static final long TIMEOUT_MILLIS = TimeUnit.MINUTES.toMillis(10);

        private JobService mJobService;
        private JobParameters mParams;
        private AppCollector mCollector;
        private File mOutputFile;
        private File mDownloadsDirectory;
        private Context mContext;
        private long mSystemSize;

        public void setDownloadsDirectory(File file) {
            mDownloadsDirectory = file;
        }

        public void setAppCollector(AppCollector collector) {
            mCollector = collector;
        }

        public void setLogOutputFile(File file) {
            mOutputFile = file;
        }

        public void setSystemSize(long size) {
            mSystemSize = size;
        }

        public void setContext(Context context) {
            mContext = context;
        }

        public void setJobService(JobService jobService, JobParameters params) {
            mJobService = jobService;
            mParams = params;
        }

        public void run() {
            FileCollector.MeasurementResult mainCategories;
            try {
                mainCategories = FileCollector.getMeasurementResult(mContext);
            } catch (IllegalStateException e) {
                // This can occur if installd has an issue.
                Log.e(TAG, "Error while measuring storage", e);
                finishJob(true);
                return;
            }
            FileCollector.MeasurementResult downloads =
                    FileCollector.getMeasurementResult(mDownloadsDirectory);

            boolean needsReschedule = true;
            List<PackageStats> stats = mCollector.getPackageStats(TIMEOUT_MILLIS);
            if (stats != null) {
                needsReschedule = false;
                logToFile(mainCategories, downloads, stats, mSystemSize);
            } else {
                Log.w(TAG, "Timed out while fetching package stats.");
            }

            finishJob(needsReschedule);
        }

        private void logToFile(MeasurementResult mainCategories, MeasurementResult downloads,
                List<PackageStats> stats, long systemSize) {
            DiskStatsFileLogger logger = new DiskStatsFileLogger(mainCategories, downloads, stats,
                    systemSize);
            try {
                mOutputFile.createNewFile();
                logger.dumpToFile(mOutputFile);
            } catch (IOException e) {
                Log.e(TAG, "Exception while writing opportunistic disk file cache.", e);
            }
        }

        private void finishJob(boolean needsReschedule) {
            if (mJobService != null) {
                mJobService.jobFinished(mParams, needsReschedule);
            }
        }
    }
}