/*
 * 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/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 android.app.job.JobInfo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.UserHandle;
import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseBooleanArray;

import com.android.internal.util.ArrayUtils;
import com.android.server.DeviceIdleController;
import com.android.server.LocalServices;
import com.android.server.job.JobSchedulerService;
import com.android.server.job.JobStore;

import java.io.PrintWriter;
import java.util.Arrays;

/**
 * When device is dozing, set constraint for all jobs, except whitelisted apps, as not satisfied.
 * When device is not dozing, set constraint for all jobs as satisfied.
 */
public final class DeviceIdleJobsController extends StateController {

    private static final String LOG_TAG = "DeviceIdleJobsController";
    private static final boolean LOG_DEBUG = false;
    private static final long BACKGROUND_JOBS_DELAY = 3000;

    static final int PROCESS_BACKGROUND_JOBS = 1;

    // Singleton factory
    private static Object sCreationLock = new Object();
    private static DeviceIdleJobsController sController;

    /**
     * These are jobs added with a special flag to indicate that they should be exempted from doze
     * when the app is temp whitelisted or in the foreground.
     */
    private final ArraySet<JobStatus> mAllowInIdleJobs;
    private final SparseBooleanArray mForegroundUids;
    private final DeviceIdleUpdateFunctor mDeviceIdleUpdateFunctor;
    private final DeviceIdleJobsDelayHandler mHandler;
    private final JobSchedulerService mJobSchedulerService;
    private final PowerManager mPowerManager;
    private final DeviceIdleController.LocalService mLocalDeviceIdleController;

    /**
     * True when in device idle mode, so we don't want to schedule any jobs.
     */
    private boolean mDeviceIdleMode;
    private int[] mDeviceIdleWhitelistAppIds;
    private int[] mPowerSaveTempWhitelistAppIds;

    /**
     * Returns a singleton for the DeviceIdleJobsController
     */
    public static DeviceIdleJobsController get(JobSchedulerService service) {
        synchronized (sCreationLock) {
            if (sController == null) {
                sController = new DeviceIdleJobsController(service, service.getContext(),
                        service.getLock());
            }
            return sController;
        }
    }

    // onReceive
    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            switch (intent.getAction()) {
                case PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED:
                case PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED:
                    updateIdleMode(mPowerManager != null && (mPowerManager.isDeviceIdleMode()
                            || mPowerManager.isLightDeviceIdleMode()));
                    break;
                case PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED:
                    synchronized (mLock) {
                        mDeviceIdleWhitelistAppIds =
                                mLocalDeviceIdleController.getPowerSaveWhitelistUserAppIds();
                        if (LOG_DEBUG) {
                            Slog.d(LOG_TAG, "Got whitelist "
                                    + Arrays.toString(mDeviceIdleWhitelistAppIds));
                        }
                    }
                    break;
                case PowerManager.ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED:
                    synchronized (mLock) {
                        mPowerSaveTempWhitelistAppIds =
                                mLocalDeviceIdleController.getPowerSaveTempWhitelistAppIds();
                        if (LOG_DEBUG) {
                            Slog.d(LOG_TAG, "Got temp whitelist "
                                    + Arrays.toString(mPowerSaveTempWhitelistAppIds));
                        }
                        boolean changed = false;
                        for (int i = 0; i < mAllowInIdleJobs.size(); i++) {
                            changed |= updateTaskStateLocked(mAllowInIdleJobs.valueAt(i));
                        }
                        if (changed) {
                            mStateChangedListener.onControllerStateChanged();
                        }
                    }
                    break;
            }
        }
    };

    private DeviceIdleJobsController(JobSchedulerService jobSchedulerService, Context context,
            Object lock) {
        super(jobSchedulerService, context, lock);

        mJobSchedulerService = jobSchedulerService;
        mHandler = new DeviceIdleJobsDelayHandler(context.getMainLooper());
        // Register for device idle mode changes
        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
        mLocalDeviceIdleController =
                LocalServices.getService(DeviceIdleController.LocalService.class);
        mDeviceIdleWhitelistAppIds = mLocalDeviceIdleController.getPowerSaveWhitelistUserAppIds();
        mPowerSaveTempWhitelistAppIds =
                mLocalDeviceIdleController.getPowerSaveTempWhitelistAppIds();
        mDeviceIdleUpdateFunctor = new DeviceIdleUpdateFunctor();
        mAllowInIdleJobs = new ArraySet<>();
        mForegroundUids = new SparseBooleanArray();
        final IntentFilter filter = new IntentFilter();
        filter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
        filter.addAction(PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED);
        filter.addAction(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
        filter.addAction(PowerManager.ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED);
        mContext.registerReceiverAsUser(
                mBroadcastReceiver, UserHandle.ALL, filter, null, null);
    }

    void updateIdleMode(boolean enabled) {
        boolean changed = false;
        synchronized (mLock) {
            if (mDeviceIdleMode != enabled) {
                changed = true;
            }
            mDeviceIdleMode = enabled;
            if (LOG_DEBUG) Slog.d(LOG_TAG, "mDeviceIdleMode=" + mDeviceIdleMode);
            if (enabled) {
                mHandler.removeMessages(PROCESS_BACKGROUND_JOBS);
                mJobSchedulerService.getJobStore().forEachJob(mDeviceIdleUpdateFunctor);
            } else {
                // When coming out of doze, process all foreground uids immediately, while others
                // will be processed after a delay of 3 seconds.
                for (int i = 0; i < mForegroundUids.size(); i++) {
                    if (mForegroundUids.valueAt(i)) {
                        mJobSchedulerService.getJobStore().forEachJobForSourceUid(
                                mForegroundUids.keyAt(i), mDeviceIdleUpdateFunctor);
                    }
                }
                mHandler.sendEmptyMessageDelayed(PROCESS_BACKGROUND_JOBS, BACKGROUND_JOBS_DELAY);
            }
        }
        // Inform the job scheduler service about idle mode changes
        if (changed) {
            mStateChangedListener.onDeviceIdleStateChanged(enabled);
        }
    }

    /**
     *  Called by jobscheduler service to report uid state changes between active and idle
     */
    public void setUidActiveLocked(int uid, boolean active) {
        final boolean changed = (active != mForegroundUids.get(uid));
        if (!changed) {
            return;
        }
        if (LOG_DEBUG) {
            Slog.d(LOG_TAG, "uid " + uid + " going " + (active ? "active" : "inactive"));
        }
        mForegroundUids.put(uid, active);
        mDeviceIdleUpdateFunctor.mChanged = false;
        mJobSchedulerService.getJobStore().forEachJobForSourceUid(uid, mDeviceIdleUpdateFunctor);
        if (mDeviceIdleUpdateFunctor.mChanged) {
            mStateChangedListener.onControllerStateChanged();
        }
    }

    /**
     * Checks if the given job's scheduling app id exists in the device idle user whitelist.
     */
    boolean isWhitelistedLocked(JobStatus job) {
        return Arrays.binarySearch(mDeviceIdleWhitelistAppIds,
                UserHandle.getAppId(job.getSourceUid())) >= 0;
    }

    /**
     * Checks if the given job's scheduling app id exists in the device idle temp whitelist.
     */
    boolean isTempWhitelistedLocked(JobStatus job) {
        return ArrayUtils.contains(mPowerSaveTempWhitelistAppIds,
                UserHandle.getAppId(job.getSourceUid()));
    }

    private boolean updateTaskStateLocked(JobStatus task) {
        final boolean allowInIdle = ((task.getFlags()&JobInfo.FLAG_IMPORTANT_WHILE_FOREGROUND) != 0)
                && (mForegroundUids.get(task.getSourceUid()) || isTempWhitelistedLocked(task));
        final boolean whitelisted = isWhitelistedLocked(task);
        final boolean enableTask = !mDeviceIdleMode || whitelisted || allowInIdle;
        return task.setDeviceNotDozingConstraintSatisfied(enableTask, whitelisted);
    }

    @Override
    public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
        if ((jobStatus.getFlags()&JobInfo.FLAG_IMPORTANT_WHILE_FOREGROUND) != 0) {
            mAllowInIdleJobs.add(jobStatus);
        }
        updateTaskStateLocked(jobStatus);
    }

    @Override
    public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob,
            boolean forUpdate) {
        if ((jobStatus.getFlags()&JobInfo.FLAG_IMPORTANT_WHILE_FOREGROUND) != 0) {
            mAllowInIdleJobs.remove(jobStatus);
        }
    }

    @Override
    public void dumpControllerStateLocked(final PrintWriter pw, final int filterUid) {
        pw.println("DeviceIdleJobsController");
        pw.println("mDeviceIdleMode=" + mDeviceIdleMode);
        mJobSchedulerService.getJobStore().forEachJob(new JobStore.JobStatusFunctor() {
            @Override public void process(JobStatus jobStatus) {
                if (!jobStatus.shouldDump(filterUid)) {
                    return;
                }
                pw.print("  #");
                jobStatus.printUniqueId(pw);
                pw.print(" from ");
                UserHandle.formatUid(pw, jobStatus.getSourceUid());
                pw.print(": ");
                pw.print(jobStatus.getSourcePackageName());
                pw.print((jobStatus.satisfiedConstraints
                        & JobStatus.CONSTRAINT_DEVICE_NOT_DOZING) != 0
                                ? " RUNNABLE" : " WAITING");
                if (jobStatus.dozeWhitelisted) {
                    pw.print(" WHITELISTED");
                }
                if (mAllowInIdleJobs.contains(jobStatus)) {
                    pw.print(" ALLOWED_IN_DOZE");
                }
                pw.println();
            }
        });
    }

    final class DeviceIdleUpdateFunctor implements JobStore.JobStatusFunctor {
        boolean mChanged;

        @Override
        public void process(JobStatus jobStatus) {
            mChanged |= updateTaskStateLocked(jobStatus);
        }
    }

    final class DeviceIdleJobsDelayHandler extends Handler {
        public DeviceIdleJobsDelayHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case PROCESS_BACKGROUND_JOBS:
                    // Just process all the jobs, the ones in foreground should already be running.
                    synchronized (mLock) {
                        mDeviceIdleUpdateFunctor.mChanged = false;
                        mJobSchedulerService.getJobStore().forEachJob(mDeviceIdleUpdateFunctor);
                        if (mDeviceIdleUpdateFunctor.mChanged) {
                            mStateChangedListener.onControllerStateChanged();
                        }
                    }
                    break;
            }
        }
    }
}