/*
 * Copyright (C) 2018 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.internal.os;

import android.annotation.Nullable;
import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.KeyValueListParser;
import android.util.Range;
import android.util.Slog;

import com.android.internal.annotations.VisibleForTesting;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Service that handles settings for {@link KernelCpuThreadReader}
 *
 * <p>N.B.: The `collected_uids` setting takes a string representation of what UIDs to collect data
 * for. A string representation is used as we will want to express UID ranges, therefore an integer
 * array could not be used. The format of the string representation is detailed here: {@link
 * UidPredicate#fromString}.
 *
 * @hide Only for use within the system server
 */
public class KernelCpuThreadReaderSettingsObserver extends ContentObserver {
    private static final String TAG = "KernelCpuThreadReaderSettingsObserver";

    /**
     * The number of frequency buckets to report
     */
    private static final String NUM_BUCKETS_SETTINGS_KEY = "num_buckets";
    private static final int NUM_BUCKETS_DEFAULT = 8;

    /**
     * List of UIDs to report data for
     */
    private static final String COLLECTED_UIDS_SETTINGS_KEY = "collected_uids";
    private static final String COLLECTED_UIDS_DEFAULT = "0-0;1000-1000";

    /**
     * Minimum total CPU usage to report
     */
    private static final String MINIMUM_TOTAL_CPU_USAGE_MILLIS_SETTINGS_KEY =
            "minimum_total_cpu_usage_millis";
    private static final int MINIMUM_TOTAL_CPU_USAGE_MILLIS_DEFAULT = 10000;

    private final Context mContext;

    @Nullable
    private final KernelCpuThreadReader mKernelCpuThreadReader;

    /**
     * @return returns a created {@link KernelCpuThreadReader} that will be modified by any
     * change in settings, returns null if creation failed
     */
    @Nullable
    public static KernelCpuThreadReader getSettingsModifiedReader(Context context) {
        // Create the observer
        KernelCpuThreadReaderSettingsObserver settingsObserver =
                new KernelCpuThreadReaderSettingsObserver(context);
        // Register the observer to listen for setting changes
        Uri settingsUri =
                Settings.Global.getUriFor(Settings.Global.KERNEL_CPU_THREAD_READER);
        context.getContentResolver().registerContentObserver(
                settingsUri, false, settingsObserver, UserHandle.USER_SYSTEM);
        // Return the observer's reader
        return settingsObserver.mKernelCpuThreadReader;
    }

    private KernelCpuThreadReaderSettingsObserver(Context context) {
        super(BackgroundThread.getHandler());
        mContext = context;
        mKernelCpuThreadReader = KernelCpuThreadReader.create(
                NUM_BUCKETS_DEFAULT,
                UidPredicate.fromString(COLLECTED_UIDS_DEFAULT),
                MINIMUM_TOTAL_CPU_USAGE_MILLIS_DEFAULT);
    }

    @Override
    public void onChange(boolean selfChange, Uri uri, int userId) {
        updateReader();
    }

    /**
     * Update the reader with new settings
     */
    private void updateReader() {
        if (mKernelCpuThreadReader == null) {
            return;
        }

        final KeyValueListParser parser = new KeyValueListParser(',');
        try {
            parser.setString(Settings.Global.getString(
                    mContext.getContentResolver(), Settings.Global.KERNEL_CPU_THREAD_READER));
        } catch (IllegalArgumentException e) {
            Slog.e(TAG, "Bad settings", e);
            return;
        }

        final UidPredicate uidPredicate;
        try {
            uidPredicate = UidPredicate.fromString(
                    parser.getString(COLLECTED_UIDS_SETTINGS_KEY, COLLECTED_UIDS_DEFAULT));
        } catch (NumberFormatException e) {
            Slog.w(TAG, "Failed to get UID predicate", e);
            return;
        }

        mKernelCpuThreadReader.setNumBuckets(
                parser.getInt(NUM_BUCKETS_SETTINGS_KEY, NUM_BUCKETS_DEFAULT));
        mKernelCpuThreadReader.setUidPredicate(uidPredicate);
        mKernelCpuThreadReader.setMinimumTotalCpuUsageMillis(parser.getInt(
                MINIMUM_TOTAL_CPU_USAGE_MILLIS_SETTINGS_KEY,
                MINIMUM_TOTAL_CPU_USAGE_MILLIS_DEFAULT));
    }

    /**
     * Check whether a UID belongs to a set of UIDs
     */
    @VisibleForTesting
    public static class UidPredicate implements Predicate<Integer> {
        private static final Pattern UID_RANGE_PATTERN = Pattern.compile("([0-9]+)-([0-9]+)");
        private static final String UID_SPECIFIER_DELIMITER = ";";
        private final List<Range<Integer>> mAcceptedUidRanges;

        /**
         * Create a UID predicate from a string representing a list of UID ranges
         *
         * <p>UID ranges are a pair of integers separated by a '-'. If you want to specify a single
         * UID (e.g. UID 1000), you can use {@code 1000-1000}. Lists of ranges are separated by
         * a single ';'. For example, this would be a valid string representation: {@code
         * "1000-1999;2003-2003;2004-2004;2050-2060"}.
         *
         * <p>We do not use ',' to delimit as it is already used in separating different setting
         * arguments.
         *
         * @throws NumberFormatException    if the input string is incorrectly formatted
         * @throws IllegalArgumentException if an UID range has a lower end than start
         */
        @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
        public static UidPredicate fromString(String predicateString) throws NumberFormatException {
            final List<Range<Integer>> acceptedUidRanges = new ArrayList<>();
            for (String uidSpecifier : predicateString.split(UID_SPECIFIER_DELIMITER)) {
                final Matcher uidRangeMatcher = UID_RANGE_PATTERN.matcher(uidSpecifier);
                if (!uidRangeMatcher.matches()) {
                    throw new NumberFormatException(
                            "Failed to recognize as number range: " + uidSpecifier);
                }
                acceptedUidRanges.add(Range.create(
                        Integer.parseInt(uidRangeMatcher.group(1)),
                        Integer.parseInt(uidRangeMatcher.group(2))));
            }
            return new UidPredicate(acceptedUidRanges);
        }

        private UidPredicate(List<Range<Integer>> acceptedUidRanges) {
            mAcceptedUidRanges = acceptedUidRanges;
        }

        @Override
        public boolean test(Integer uid) {
            for (int i = 0; i < mAcceptedUidRanges.size(); i++) {
                if (mAcceptedUidRanges.get(i).contains(uid)) {
                    return true;
                }
            }
            return false;
        }
    }
}
