/*
 * 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 com.android.server.job.controllers;

import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.UserHandle;
import android.util.ArraySet;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.job.JobSchedulerService;
import com.android.server.job.StateChangedListener;
import com.android.server.job.StateControllerProto;
import com.android.server.storage.DeviceStorageMonitorService;

import java.io.PrintWriter;

/**
 * Simple controller that tracks the status of the device's storage.
 */
public final class StorageController extends StateController {
    private static final String TAG = "JobScheduler.Stor";

    private static final Object sCreationLock = new Object();
    private static volatile StorageController sController;

    private final ArraySet<JobStatus> mTrackedTasks = new ArraySet<JobStatus>();
    private StorageTracker mStorageTracker;

    public static StorageController get(JobSchedulerService taskManagerService) {
        synchronized (sCreationLock) {
            if (sController == null) {
                sController = new StorageController(taskManagerService,
                        taskManagerService.getContext(), taskManagerService.getLock());
            }
        }
        return sController;
    }

    @VisibleForTesting
    public StorageTracker getTracker() {
        return mStorageTracker;
    }

    @VisibleForTesting
    public static StorageController getForTesting(StateChangedListener stateChangedListener,
            Context context) {
        return new StorageController(stateChangedListener, context, new Object());
    }

    private StorageController(StateChangedListener stateChangedListener, Context context,
            Object lock) {
        super(stateChangedListener, context, lock);
        mStorageTracker = new StorageTracker();
        mStorageTracker.startTracking();
    }

    @Override
    public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) {
        if (taskStatus.hasStorageNotLowConstraint()) {
            mTrackedTasks.add(taskStatus);
            taskStatus.setTrackingController(JobStatus.TRACKING_STORAGE);
            taskStatus.setStorageNotLowConstraintSatisfied(mStorageTracker.isStorageNotLow());
        }
    }

    @Override
    public void maybeStopTrackingJobLocked(JobStatus taskStatus, JobStatus incomingJob,
            boolean forUpdate) {
        if (taskStatus.clearTrackingController(JobStatus.TRACKING_STORAGE)) {
            mTrackedTasks.remove(taskStatus);
        }
    }

    private void maybeReportNewStorageState() {
        final boolean storageNotLow = mStorageTracker.isStorageNotLow();
        boolean reportChange = false;
        synchronized (mLock) {
            for (int i = mTrackedTasks.size() - 1; i >= 0; i--) {
                final JobStatus ts = mTrackedTasks.valueAt(i);
                boolean previous = ts.setStorageNotLowConstraintSatisfied(storageNotLow);
                if (previous != storageNotLow) {
                    reportChange = true;
                }
            }
        }
        // Let the scheduler know that state has changed. This may or may not result in an
        // execution.
        if (reportChange) {
            mStateChangedListener.onControllerStateChanged();
        }
        // Also tell the scheduler that any ready jobs should be flushed.
        if (storageNotLow) {
            mStateChangedListener.onRunJobNow(null);
        }
    }

    public final class StorageTracker extends BroadcastReceiver {
        /**
         * Track whether storage is low.
         */
        private boolean mStorageLow;
        /** Sequence number of last broadcast. */
        private int mLastStorageSeq = -1;

        public StorageTracker() {
        }

        public void startTracking() {
            IntentFilter filter = new IntentFilter();

            // Storage status.  Just need to register, since STORAGE_LOW is a sticky
            // broadcast we will receive that if it is currently active.
            filter.addAction(Intent.ACTION_DEVICE_STORAGE_LOW);
            filter.addAction(Intent.ACTION_DEVICE_STORAGE_OK);
            mContext.registerReceiver(this, filter);
        }

        public boolean isStorageNotLow() {
            return !mStorageLow;
        }

        public int getSeq() {
            return mLastStorageSeq;
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            onReceiveInternal(intent);
        }

        @VisibleForTesting
        public void onReceiveInternal(Intent intent) {
            final String action = intent.getAction();
            mLastStorageSeq = intent.getIntExtra(DeviceStorageMonitorService.EXTRA_SEQUENCE,
                    mLastStorageSeq);
            if (Intent.ACTION_DEVICE_STORAGE_LOW.equals(action)) {
                if (DEBUG) {
                    Slog.d(TAG, "Available storage too low to do work. @ "
                            + sElapsedRealtimeClock.millis());
                }
                mStorageLow = true;
            } else if (Intent.ACTION_DEVICE_STORAGE_OK.equals(action)) {
                if (DEBUG) {
                    Slog.d(TAG, "Available stoage high enough to do work. @ "
                            + sElapsedRealtimeClock.millis());
                }
                mStorageLow = false;
                maybeReportNewStorageState();
            }
        }
    }

    @Override
    public void dumpControllerStateLocked(PrintWriter pw, int filterUid) {
        pw.print("Storage: not low = ");
        pw.print(mStorageTracker.isStorageNotLow());
        pw.print(", seq=");
        pw.println(mStorageTracker.getSeq());
        pw.print("Tracking ");
        pw.print(mTrackedTasks.size());
        pw.println(":");
        for (int i = 0; i < mTrackedTasks.size(); i++) {
            final JobStatus js = mTrackedTasks.valueAt(i);
            if (!js.shouldDump(filterUid)) {
                continue;
            }
            pw.print("  #");
            js.printUniqueId(pw);
            pw.print(" from ");
            UserHandle.formatUid(pw, js.getSourceUid());
            pw.println();
        }
    }

    @Override
    public void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId, int filterUid) {
        final long token = proto.start(fieldId);
        final long mToken = proto.start(StateControllerProto.STORAGE);

        proto.write(StateControllerProto.StorageController.IS_STORAGE_NOT_LOW,
                mStorageTracker.isStorageNotLow());
        proto.write(StateControllerProto.StorageController.LAST_BROADCAST_SEQUENCE_NUMBER,
                mStorageTracker.getSeq());

        for (int i = 0; i < mTrackedTasks.size(); i++) {
            final JobStatus js = mTrackedTasks.valueAt(i);
            if (!js.shouldDump(filterUid)) {
                continue;
            }
            final long jsToken = proto.start(StateControllerProto.StorageController.TRACKED_JOBS);
            js.writeToShortProto(proto, StateControllerProto.StorageController.TrackedJob.INFO);
            proto.write(StateControllerProto.StorageController.TrackedJob.SOURCE_UID,
                    js.getSourceUid());
            proto.end(jsToken);
        }

        proto.end(mToken);
        proto.end(token);
    }
}
