/*
 * 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 android.util.proto.ProtoOutputStream;

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 com.android.server.job.StateControllerProto;
import com.android.server.job.StateControllerProto.DeviceIdleJobsController.TrackedJob;

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

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

        proto.write(StateControllerProto.DeviceIdleJobsController.IS_DEVICE_IDLE_MODE,
                mDeviceIdleMode);
        mJobSchedulerService.getJobStore().forEachJob(new JobStore.JobStatusFunctor() {
            @Override public void process(JobStatus jobStatus) {
                if (!jobStatus.shouldDump(filterUid)) {
                    return;
                }
                final long jsToken =
                        proto.start(StateControllerProto.DeviceIdleJobsController.TRACKED_JOBS);

                jobStatus.writeToShortProto(proto, TrackedJob.INFO);
                proto.write(TrackedJob.SOURCE_UID, jobStatus.getSourceUid());
                proto.write(TrackedJob.SOURCE_PACKAGE_NAME, jobStatus.getSourcePackageName());
                proto.write(TrackedJob.ARE_CONSTRAINTS_SATISFIED,
                        (jobStatus.satisfiedConstraints &
                            JobStatus.CONSTRAINT_DEVICE_NOT_DOZING) != 0);
                proto.write(TrackedJob.IS_DOZE_WHITELISTED, jobStatus.dozeWhitelisted);
                proto.write(TrackedJob.IS_ALLOWED_IN_DOZE, mAllowInIdleJobs.contains(jobStatus));

                proto.end(jsToken);
            }
        });

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

    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;
            }
        }
    }
}
