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

import android.annotation.UserIdInt;
import android.app.job.JobInfo;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;

import com.android.server.job.JobSchedulerService;
import com.android.server.job.StateControllerProto;
import com.android.server.job.StateControllerProto.ContentObserverController.Observer.TriggerContentData;

import java.util.ArrayList;
import java.util.function.Predicate;

/**
 * Controller for monitoring changes to content URIs through a ContentObserver.
 */
public final class ContentObserverController extends StateController {
    private static final String TAG = "JobScheduler.ContentObserver";
    private static final boolean DEBUG = JobSchedulerService.DEBUG
            || Log.isLoggable(TAG, Log.DEBUG);

    /**
     * Maximum number of changing URIs we will batch together to report.
     * XXX Should be smarter about this, restricting it by the maximum number
     * of characters we will retain.
     */
    private static final int MAX_URIS_REPORTED = 50;

    /**
     * At this point we consider it urgent to schedule the job ASAP.
     */
    private static final int URIS_URGENT_THRESHOLD = 40;

    final private ArraySet<JobStatus> mTrackedTasks = new ArraySet<>();
    /**
     * Per-userid {@link JobInfo.TriggerContentUri} keyed ContentObserver cache.
     */
    final SparseArray<ArrayMap<JobInfo.TriggerContentUri, ObserverInstance>> mObservers =
            new SparseArray<>();
    final Handler mHandler;

    public ContentObserverController(JobSchedulerService service) {
        super(service);
        mHandler = new Handler(mContext.getMainLooper());
    }

    @Override
    public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) {
        if (taskStatus.hasContentTriggerConstraint()) {
            final long nowElapsed = sElapsedRealtimeClock.millis();
            if (taskStatus.contentObserverJobInstance == null) {
                taskStatus.contentObserverJobInstance = new JobInstance(taskStatus);
            }
            if (DEBUG) {
                Slog.i(TAG, "Tracking content-trigger job " + taskStatus);
            }
            mTrackedTasks.add(taskStatus);
            taskStatus.setTrackingController(JobStatus.TRACKING_CONTENT);
            boolean havePendingUris = false;
            // If there is a previous job associated with the new job, propagate over
            // any pending content URI trigger reports.
            if (taskStatus.contentObserverJobInstance.mChangedAuthorities != null) {
                havePendingUris = true;
            }
            // If we have previously reported changed authorities/uris, then we failed
            // to complete the job with them so will re-record them to report again.
            if (taskStatus.changedAuthorities != null) {
                havePendingUris = true;
                if (taskStatus.contentObserverJobInstance.mChangedAuthorities == null) {
                    taskStatus.contentObserverJobInstance.mChangedAuthorities
                            = new ArraySet<>();
                }
                for (String auth : taskStatus.changedAuthorities) {
                    taskStatus.contentObserverJobInstance.mChangedAuthorities.add(auth);
                }
                if (taskStatus.changedUris != null) {
                    if (taskStatus.contentObserverJobInstance.mChangedUris == null) {
                        taskStatus.contentObserverJobInstance.mChangedUris = new ArraySet<>();
                    }
                    for (Uri uri : taskStatus.changedUris) {
                        taskStatus.contentObserverJobInstance.mChangedUris.add(uri);
                    }
                }
            }
            taskStatus.changedAuthorities = null;
            taskStatus.changedUris = null;
            taskStatus.setContentTriggerConstraintSatisfied(nowElapsed, havePendingUris);
        }
        if (lastJob != null && lastJob.contentObserverJobInstance != null) {
            // And now we can detach the instance state from the last job.
            lastJob.contentObserverJobInstance.detachLocked();
            lastJob.contentObserverJobInstance = null;
        }
    }

    @Override
    public void prepareForExecutionLocked(JobStatus taskStatus) {
        if (taskStatus.hasContentTriggerConstraint()) {
            if (taskStatus.contentObserverJobInstance != null) {
                taskStatus.changedUris = taskStatus.contentObserverJobInstance.mChangedUris;
                taskStatus.changedAuthorities
                        = taskStatus.contentObserverJobInstance.mChangedAuthorities;
                taskStatus.contentObserverJobInstance.mChangedUris = null;
                taskStatus.contentObserverJobInstance.mChangedAuthorities = null;
            }
        }
    }

    @Override
    public void unprepareFromExecutionLocked(JobStatus taskStatus) {
        if (taskStatus.hasContentTriggerConstraint()) {
            if (taskStatus.contentObserverJobInstance != null) {
                if (taskStatus.contentObserverJobInstance.mChangedUris == null) {
                    taskStatus.contentObserverJobInstance.mChangedUris = taskStatus.changedUris;
                } else {
                    taskStatus.contentObserverJobInstance.mChangedUris
                            .addAll(taskStatus.changedUris);
                }
                if (taskStatus.contentObserverJobInstance.mChangedAuthorities == null) {
                    taskStatus.contentObserverJobInstance.mChangedAuthorities =
                            taskStatus.changedAuthorities;
                } else {
                    taskStatus.contentObserverJobInstance.mChangedAuthorities
                            .addAll(taskStatus.changedAuthorities);
                }
                taskStatus.changedUris = null;
                taskStatus.changedAuthorities = null;
            }
        }
    }

    @Override
    public void maybeStopTrackingJobLocked(JobStatus taskStatus, JobStatus incomingJob,
            boolean forUpdate) {
        if (taskStatus.clearTrackingController(JobStatus.TRACKING_CONTENT)) {
            mTrackedTasks.remove(taskStatus);
            if (taskStatus.contentObserverJobInstance != null) {
                taskStatus.contentObserverJobInstance.unscheduleLocked();
                if (incomingJob != null) {
                    if (taskStatus.contentObserverJobInstance != null
                            && taskStatus.contentObserverJobInstance.mChangedAuthorities != null) {
                        // We are stopping this job, but it is going to be replaced by this given
                        // incoming job.  We want to propagate our state over to it, so we don't
                        // lose any content changes that had happened since the last one started.
                        // If there is a previous job associated with the new job, propagate over
                        // any pending content URI trigger reports.
                        if (incomingJob.contentObserverJobInstance == null) {
                            incomingJob.contentObserverJobInstance = new JobInstance(incomingJob);
                        }
                        incomingJob.contentObserverJobInstance.mChangedAuthorities
                                = taskStatus.contentObserverJobInstance.mChangedAuthorities;
                        incomingJob.contentObserverJobInstance.mChangedUris
                                = taskStatus.contentObserverJobInstance.mChangedUris;
                        taskStatus.contentObserverJobInstance.mChangedAuthorities = null;
                        taskStatus.contentObserverJobInstance.mChangedUris = null;
                    }
                    // We won't detach the content observers here, because we want to
                    // allow them to continue monitoring so we don't miss anything...  and
                    // since we are giving an incomingJob here, we know this will be
                    // immediately followed by a start tracking of that job.
                } else {
                    // But here there is no incomingJob, so nothing coming up, so time to detach.
                    taskStatus.contentObserverJobInstance.detachLocked();
                    taskStatus.contentObserverJobInstance = null;
                }
            }
            if (DEBUG) {
                Slog.i(TAG, "No longer tracking job " + taskStatus);
            }
        }
    }

    @Override
    public void rescheduleForFailureLocked(JobStatus newJob, JobStatus failureToReschedule) {
        if (failureToReschedule.hasContentTriggerConstraint()
                && newJob.hasContentTriggerConstraint()) {
            // Our job has failed, and we are scheduling a new job for it.
            // Copy the last reported content changes in to the new job, so when
            // we schedule the new one we will pick them up and report them again.
            newJob.changedAuthorities = failureToReschedule.changedAuthorities;
            newJob.changedUris = failureToReschedule.changedUris;
        }
    }

    final class ObserverInstance extends ContentObserver {
        final JobInfo.TriggerContentUri mUri;
        final @UserIdInt int mUserId;
        final ArraySet<JobInstance> mJobs = new ArraySet<>();

        public ObserverInstance(Handler handler, JobInfo.TriggerContentUri uri,
                @UserIdInt int userId) {
            super(handler);
            mUri = uri;
            mUserId = userId;
        }

        @Override
        public void onChange(boolean selfChange, Uri uri) {
            if (DEBUG) {
                Slog.i(TAG, "onChange(self=" + selfChange + ") for " + uri
                        + " when mUri=" + mUri + " mUserId=" + mUserId);
            }
            synchronized (mLock) {
                final int N = mJobs.size();
                for (int i=0; i<N; i++) {
                    JobInstance inst = mJobs.valueAt(i);
                    if (inst.mChangedUris == null) {
                        inst.mChangedUris = new ArraySet<>();
                    }
                    if (inst.mChangedUris.size() < MAX_URIS_REPORTED) {
                        inst.mChangedUris.add(uri);
                    }
                    if (inst.mChangedAuthorities == null) {
                        inst.mChangedAuthorities = new ArraySet<>();
                    }
                    inst.mChangedAuthorities.add(uri.getAuthority());
                    inst.scheduleLocked();
                }
            }
        }
    }

    static final class TriggerRunnable implements Runnable {
        final JobInstance mInstance;

        TriggerRunnable(JobInstance instance) {
            mInstance = instance;
        }

        @Override public void run() {
            mInstance.trigger();
        }
    }

    final class JobInstance {
        final ArrayList<ObserverInstance> mMyObservers = new ArrayList<>();
        final JobStatus mJobStatus;
        final Runnable mExecuteRunner;
        final Runnable mTimeoutRunner;
        ArraySet<Uri> mChangedUris;
        ArraySet<String> mChangedAuthorities;

        boolean mTriggerPending;

        // This constructor must be called with the master job scheduler lock held.
        JobInstance(JobStatus jobStatus) {
            mJobStatus = jobStatus;
            mExecuteRunner = new TriggerRunnable(this);
            mTimeoutRunner = new TriggerRunnable(this);
            final JobInfo.TriggerContentUri[] uris = jobStatus.getJob().getTriggerContentUris();
            final int sourceUserId = jobStatus.getSourceUserId();
            ArrayMap<JobInfo.TriggerContentUri, ObserverInstance> observersOfUser =
                    mObservers.get(sourceUserId);
            if (observersOfUser == null) {
                observersOfUser = new ArrayMap<>();
                mObservers.put(sourceUserId, observersOfUser);
            }
            if (uris != null) {
                for (JobInfo.TriggerContentUri uri : uris) {
                    ObserverInstance obs = observersOfUser.get(uri);
                    if (obs == null) {
                        obs = new ObserverInstance(mHandler, uri, jobStatus.getSourceUserId());
                        observersOfUser.put(uri, obs);
                        final boolean andDescendants = (uri.getFlags() &
                                JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS) != 0;
                        if (DEBUG) {
                            Slog.v(TAG, "New observer " + obs + " for " + uri.getUri()
                                    + " andDescendants=" + andDescendants
                                    + " sourceUserId=" + sourceUserId);
                        }
                        mContext.getContentResolver().registerContentObserver(
                                uri.getUri(),
                                andDescendants,
                                obs,
                                sourceUserId
                        );
                    } else {
                        if (DEBUG) {
                            final boolean andDescendants = (uri.getFlags() &
                                    JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS) != 0;
                            Slog.v(TAG, "Reusing existing observer " + obs + " for " + uri.getUri()
                                    + " andDescendants=" + andDescendants);
                        }
                    }
                    obs.mJobs.add(this);
                    mMyObservers.add(obs);
                }
            }
        }

        void trigger() {
            boolean reportChange = false;
            synchronized (mLock) {
                if (mTriggerPending) {
                    final long nowElapsed = sElapsedRealtimeClock.millis();
                    if (mJobStatus.setContentTriggerConstraintSatisfied(nowElapsed, true)) {
                        reportChange = true;
                    }
                    unscheduleLocked();
                }
            }
            // Let the scheduler know that state has changed. This may or may not result in an
            // execution.
            if (reportChange) {
                mStateChangedListener.onControllerStateChanged();
            }
        }

        void scheduleLocked() {
            if (!mTriggerPending) {
                mTriggerPending = true;
                mHandler.postDelayed(mTimeoutRunner, mJobStatus.getTriggerContentMaxDelay());
            }
            mHandler.removeCallbacks(mExecuteRunner);
            if (mChangedUris.size() >= URIS_URGENT_THRESHOLD) {
                // If we start getting near the limit, GO NOW!
                mHandler.post(mExecuteRunner);
            } else {
                mHandler.postDelayed(mExecuteRunner, mJobStatus.getTriggerContentUpdateDelay());
            }
        }

        void unscheduleLocked() {
            if (mTriggerPending) {
                mHandler.removeCallbacks(mExecuteRunner);
                mHandler.removeCallbacks(mTimeoutRunner);
                mTriggerPending = false;
            }
        }

        void detachLocked() {
            final int N = mMyObservers.size();
            for (int i=0; i<N; i++) {
                final ObserverInstance obs = mMyObservers.get(i);
                obs.mJobs.remove(this);
                if (obs.mJobs.size() == 0) {
                    if (DEBUG) {
                        Slog.i(TAG, "Unregistering observer " + obs + " for " + obs.mUri.getUri());
                    }
                    mContext.getContentResolver().unregisterContentObserver(obs);
                    ArrayMap<JobInfo.TriggerContentUri, ObserverInstance> observerOfUser =
                            mObservers.get(obs.mUserId);
                    if (observerOfUser != null) {
                        observerOfUser.remove(obs.mUri);
                    }
                }
            }
        }
    }

    @Override
    public void dumpControllerStateLocked(IndentingPrintWriter pw,
            Predicate<JobStatus> predicate) {
        for (int i = 0; i < mTrackedTasks.size(); i++) {
            JobStatus js = mTrackedTasks.valueAt(i);
            if (!predicate.test(js)) {
                continue;
            }
            pw.print("#");
            js.printUniqueId(pw);
            pw.print(" from ");
            UserHandle.formatUid(pw, js.getSourceUid());
            pw.println();
        }
        pw.println();

        int N = mObservers.size();
        if (N > 0) {
            pw.println("Observers:");
            pw.increaseIndent();
            for (int userIdx = 0; userIdx < N; userIdx++) {
                final int userId = mObservers.keyAt(userIdx);
                ArrayMap<JobInfo.TriggerContentUri, ObserverInstance> observersOfUser =
                        mObservers.get(userId);
                int numbOfObserversPerUser = observersOfUser.size();
                for (int observerIdx = 0 ; observerIdx < numbOfObserversPerUser; observerIdx++) {
                    ObserverInstance obs = observersOfUser.valueAt(observerIdx);
                    int M = obs.mJobs.size();
                    boolean shouldDump = false;
                    for (int j = 0; j < M; j++) {
                        JobInstance inst = obs.mJobs.valueAt(j);
                        if (predicate.test(inst.mJobStatus)) {
                            shouldDump = true;
                            break;
                        }
                    }
                    if (!shouldDump) {
                        continue;
                    }
                    JobInfo.TriggerContentUri trigger = observersOfUser.keyAt(observerIdx);
                    pw.print(trigger.getUri());
                    pw.print(" 0x");
                    pw.print(Integer.toHexString(trigger.getFlags()));
                    pw.print(" (");
                    pw.print(System.identityHashCode(obs));
                    pw.println("):");
                    pw.increaseIndent();
                    pw.println("Jobs:");
                    pw.increaseIndent();
                    for (int j = 0; j < M; j++) {
                        JobInstance inst = obs.mJobs.valueAt(j);
                        pw.print("#");
                        inst.mJobStatus.printUniqueId(pw);
                        pw.print(" from ");
                        UserHandle.formatUid(pw, inst.mJobStatus.getSourceUid());
                        if (inst.mChangedAuthorities != null) {
                            pw.println(":");
                            pw.increaseIndent();
                            if (inst.mTriggerPending) {
                                pw.print("Trigger pending: update=");
                                TimeUtils.formatDuration(
                                        inst.mJobStatus.getTriggerContentUpdateDelay(), pw);
                                pw.print(", max=");
                                TimeUtils.formatDuration(
                                        inst.mJobStatus.getTriggerContentMaxDelay(), pw);
                                pw.println();
                            }
                            pw.println("Changed Authorities:");
                            for (int k = 0; k < inst.mChangedAuthorities.size(); k++) {
                                pw.println(inst.mChangedAuthorities.valueAt(k));
                            }
                            if (inst.mChangedUris != null) {
                                pw.println("          Changed URIs:");
                                for (int k = 0; k < inst.mChangedUris.size(); k++) {
                                    pw.println(inst.mChangedUris.valueAt(k));
                                }
                            }
                            pw.decreaseIndent();
                        } else {
                            pw.println();
                        }
                    }
                    pw.decreaseIndent();
                    pw.decreaseIndent();
                }
            }
            pw.decreaseIndent();
        }
    }

    @Override
    public void dumpControllerStateLocked(ProtoOutputStream proto, long fieldId,
            Predicate<JobStatus> predicate) {
        final long token = proto.start(fieldId);
        final long mToken = proto.start(StateControllerProto.CONTENT_OBSERVER);

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

        final int n = mObservers.size();
        for (int userIdx = 0; userIdx < n; userIdx++) {
            final long oToken =
                    proto.start(StateControllerProto.ContentObserverController.OBSERVERS);
            final int userId = mObservers.keyAt(userIdx);

            proto.write(StateControllerProto.ContentObserverController.Observer.USER_ID, userId);

            ArrayMap<JobInfo.TriggerContentUri, ObserverInstance> observersOfUser =
                    mObservers.get(userId);
            int numbOfObserversPerUser = observersOfUser.size();
            for (int observerIdx = 0 ; observerIdx < numbOfObserversPerUser; observerIdx++) {
                ObserverInstance obs = observersOfUser.valueAt(observerIdx);
                int m = obs.mJobs.size();
                boolean shouldDump = false;
                for (int j = 0; j < m; j++) {
                    JobInstance inst = obs.mJobs.valueAt(j);
                    if (predicate.test(inst.mJobStatus)) {
                        shouldDump = true;
                        break;
                    }
                }
                if (!shouldDump) {
                    continue;
                }
                final long tToken = proto.start(
                        StateControllerProto.ContentObserverController.Observer.TRIGGERS);

                JobInfo.TriggerContentUri trigger = observersOfUser.keyAt(observerIdx);
                Uri u = trigger.getUri();
                if (u != null) {
                    proto.write(TriggerContentData.URI, u.toString());
                }
                proto.write(TriggerContentData.FLAGS, trigger.getFlags());

                for (int j = 0; j < m; j++) {
                    final long jToken = proto.start(TriggerContentData.JOBS);
                    JobInstance inst = obs.mJobs.valueAt(j);

                    inst.mJobStatus.writeToShortProto(proto, TriggerContentData.JobInstance.INFO);
                    proto.write(TriggerContentData.JobInstance.SOURCE_UID,
                            inst.mJobStatus.getSourceUid());

                    if (inst.mChangedAuthorities == null) {
                        proto.end(jToken);
                        continue;
                    }
                    if (inst.mTriggerPending) {
                        proto.write(TriggerContentData.JobInstance.TRIGGER_CONTENT_UPDATE_DELAY_MS,
                                inst.mJobStatus.getTriggerContentUpdateDelay());
                        proto.write(TriggerContentData.JobInstance.TRIGGER_CONTENT_MAX_DELAY_MS,
                                inst.mJobStatus.getTriggerContentMaxDelay());
                    }
                    for (int k = 0; k < inst.mChangedAuthorities.size(); k++) {
                        proto.write(TriggerContentData.JobInstance.CHANGED_AUTHORITIES,
                                inst.mChangedAuthorities.valueAt(k));
                    }
                    if (inst.mChangedUris != null) {
                        for (int k = 0; k < inst.mChangedUris.size(); k++) {
                            u = inst.mChangedUris.valueAt(k);
                            if (u != null) {
                                proto.write(TriggerContentData.JobInstance.CHANGED_URIS,
                                        u.toString());
                            }
                        }
                    }

                    proto.end(jToken);
                }

                proto.end(tToken);
            }

            proto.end(oToken);
        }

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