/*
 * Copyright (C) 2019 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.app;

import android.annotation.IntRange;
import android.annotation.NonNull;
import android.app.AppOpsManager;
import android.os.Parcel;
import android.os.Parcelable;

import com.android.internal.annotations.Immutable;
import com.android.internal.util.DataClass;

/**
 * Configuration for AppOps access messages sampling.
 */
@Immutable
/*@DataClass*/
public final class MessageSamplingConfig implements Parcelable {
    /** Op code targeted during current sampling session */
    private final @IntRange(from = -1L, to = AppOpsManager._NUM_OP - 1) int mSampledOpCode;
    /** Range of ops which should be reported during current sampling session */
    private final @IntRange(from = 0L, to = AppOpsManager._NUM_OP - 1) int mAcceptableLeftDistance;
    /** Expiration time for this sampling config */
    private final @IntRange(from = 0L) long mExpirationTimeSinceBootMillis;







    // Code below generated by codegen v1.0.14.
    //
    // DO NOT MODIFY!
    // CHECKSTYLE:OFF Generated code
    //
    // To regenerate run:
    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/com/android/internal/app/MessageSamplingConfig.java
    //
    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
    //   Settings > Editor > Code Style > Formatter Control
    //@formatter:off


    /**
     * Creates a new MessageSamplingConfig.
     *
     * @param sampledOpCode
     *   Op code targeted during current sampling session
     * @param acceptableLeftDistance
     *   Range of ops which should be reported during current sampling session
     * @param expirationTimeSinceBootMillis
     *   Expiration time for this sampling config
     */
    @DataClass.Generated.Member
    public MessageSamplingConfig(
            @IntRange(from = -1L, to = AppOpsManager._NUM_OP - 1) int sampledOpCode,
            @IntRange(from = 0L, to = AppOpsManager._NUM_OP - 1) int acceptableLeftDistance,
            @IntRange(from = 0L) long expirationTimeSinceBootMillis) {
        this.mSampledOpCode = sampledOpCode;
        com.android.internal.util.AnnotationValidations.validate(
                IntRange.class, null, mSampledOpCode,
                "from", -1L,
                "to", AppOpsManager._NUM_OP - 1);
        this.mAcceptableLeftDistance = acceptableLeftDistance;
        com.android.internal.util.AnnotationValidations.validate(
                IntRange.class, null, mAcceptableLeftDistance,
                "from", 0L,
                "to", AppOpsManager._NUM_OP - 1);
        this.mExpirationTimeSinceBootMillis = expirationTimeSinceBootMillis;
        com.android.internal.util.AnnotationValidations.validate(
                IntRange.class, null, mExpirationTimeSinceBootMillis,
                "from", 0L);

        // onConstructed(); // You can define this method to get a callback
    }

    /**
     * Op code targeted during current sampling session
     */
    @DataClass.Generated.Member
    public @IntRange(from = -1L, to = AppOpsManager._NUM_OP - 1) int getSampledOpCode() {
        return mSampledOpCode;
    }

    /**
     * Range of ops which should be reported during current sampling session
     */
    @DataClass.Generated.Member
    public @IntRange(from = 0L, to = AppOpsManager._NUM_OP - 1) int getAcceptableLeftDistance() {
        return mAcceptableLeftDistance;
    }

    /**
     * Expiration time for this sampling config
     */
    @DataClass.Generated.Member
    public @IntRange(from = 0L) long getExpirationTimeSinceBootMillis() {
        return mExpirationTimeSinceBootMillis;
    }

    @Override
    @DataClass.Generated.Member
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        // You can override field parcelling by defining methods like:
        // void parcelFieldName(Parcel dest, int flags) { ... }

        dest.writeInt(mSampledOpCode);
        dest.writeInt(mAcceptableLeftDistance);
        dest.writeLong(mExpirationTimeSinceBootMillis);
    }

    @Override
    @DataClass.Generated.Member
    public int describeContents() { return 0; }

    /** @hide */
    @SuppressWarnings({"unchecked", "RedundantCast"})
    @DataClass.Generated.Member
    /* package-private */ MessageSamplingConfig(@NonNull Parcel in) {
        // You can override field unparcelling by defining methods like:
        // static FieldType unparcelFieldName(Parcel in) { ... }

        int sampledOpCode = in.readInt();
        int acceptableLeftDistance = in.readInt();
        long expirationTimeSinceBootMillis = in.readLong();

        this.mSampledOpCode = sampledOpCode;
        com.android.internal.util.AnnotationValidations.validate(
                IntRange.class, null, mSampledOpCode,
                "from", -1L,
                "to", AppOpsManager._NUM_OP - 1);
        this.mAcceptableLeftDistance = acceptableLeftDistance;
        com.android.internal.util.AnnotationValidations.validate(
                IntRange.class, null, mAcceptableLeftDistance,
                "from", 0L,
                "to", AppOpsManager._NUM_OP - 1);
        this.mExpirationTimeSinceBootMillis = expirationTimeSinceBootMillis;
        com.android.internal.util.AnnotationValidations.validate(
                IntRange.class, null, mExpirationTimeSinceBootMillis,
                "from", 0L);

        // onConstructed(); // You can define this method to get a callback
    }

    @DataClass.Generated.Member
    public static final @NonNull Parcelable.Creator<MessageSamplingConfig> CREATOR
            = new Parcelable.Creator<MessageSamplingConfig>() {
        @Override
        public MessageSamplingConfig[] newArray(int size) {
            return new MessageSamplingConfig[size];
        }

        @Override
        public MessageSamplingConfig createFromParcel(@NonNull Parcel in) {
            return new MessageSamplingConfig(in);
        }
    };

    /*@DataClass.Generated(
            time = 1580691255495L,
            codegenVersion = "1.0.14",
            sourceFile = "frameworks/base/core/java/com/android/internal/app/MessageSamplingConfig.java",
            inputSignatures = "private final @android.annotation.IntRange(from=-1L, to=AppOpsManager._NUM_OP - 1) int mSampledOpCode\nprivate final @android.annotation.IntRange(from=0L, to=AppOpsManager._NUM_OP - 1) int mAcceptableLeftDistance\nprivate final @android.annotation.IntRange(from=0L) long mExpirationTimeSinceBootMillis\nclass MessageSamplingConfig extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass")*/
    @Deprecated
    private void __metadata() {}


    //@formatter:on
    // End of generated code

}
