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

import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.AppRestrictionController.DEVICE_CONFIG_SUBNAMESPACE_PREFIX;
import static com.android.server.am.BaseAppStateTracker.ONE_DAY;

import android.annotation.NonNull;
import android.app.ActivityManagerInternal.BroadcastEventListener;
import android.content.Context;
import android.os.AppBackgroundRestrictionsInfo;
import android.os.SystemClock;
import android.util.proto.ProtoOutputStream;

import com.android.server.am.AppBroadcastEventsTracker.AppBroadcastEventsPolicy;
import com.android.server.am.AppRestrictionController.TrackerType;
import com.android.server.am.BaseAppStateTimeSlotEventsTracker.SimpleAppStateTimeslotEvents;
import com.android.server.am.BaseAppStateTracker.Injector;

import java.io.PrintWriter;
import java.lang.reflect.Constructor;

final class AppBroadcastEventsTracker extends BaseAppStateTimeSlotEventsTracker
        <AppBroadcastEventsPolicy, SimpleAppStateTimeslotEvents> implements BroadcastEventListener {

    static final String TAG = TAG_WITH_CLASS_NAME ? "AppBroadcastEventsTracker" : TAG_AM;

    static final boolean DEBUG_APP_STATE_BROADCAST_EVENT_TRACKER = false;

    AppBroadcastEventsTracker(Context context, AppRestrictionController controller) {
        this(context, controller, null, null);
    }

    AppBroadcastEventsTracker(Context context, AppRestrictionController controller,
            Constructor<? extends Injector<AppBroadcastEventsPolicy>> injector,
            Object outerContext) {
        super(context, controller, injector, outerContext);
        mInjector.setPolicy(new AppBroadcastEventsPolicy(mInjector, this));
    }

    @Override
    public void onSendingBroadcast(String packageName, int uid) {
        if (mInjector.getPolicy().isEnabled()) {
            onNewEvent(packageName, uid);
        }
    }

    @Override
    @TrackerType int getType() {
        return AppRestrictionController.TRACKER_TYPE_BROADCAST_EVENTS;
    }

    @Override
    void onSystemReady() {
        super.onSystemReady();
        mInjector.getActivityManagerInternal().addBroadcastEventListener(this);
    }

    @Override
    public SimpleAppStateTimeslotEvents createAppStateEvents(int uid, String packageName) {
        return new SimpleAppStateTimeslotEvents(uid, packageName,
                mInjector.getPolicy().getTimeSlotSize(), TAG, mInjector.getPolicy());
    }

    @Override
    public SimpleAppStateTimeslotEvents createAppStateEvents(SimpleAppStateTimeslotEvents other) {
        return new SimpleAppStateTimeslotEvents(other);
    }

    @Override
    byte[] getTrackerInfoForStatsd(int uid) {
        final long now = SystemClock.elapsedRealtime();
        final int numOfBroadcasts = getTotalEventsLocked(uid, now);
        if (numOfBroadcasts == 0) {
            // Not interested.
            return null;
        }
        final ProtoOutputStream proto = new ProtoOutputStream();
        proto.write(AppBackgroundRestrictionsInfo.BroadcastEventsTrackerInfo.BROADCASTS_SENT,
                numOfBroadcasts);
        proto.flush();
        return proto.getBytes();
    }

    @Override
    void dump(PrintWriter pw, String prefix) {
        pw.print(prefix);
        pw.println("APP BROADCAST EVENT TRACKER:");
        super.dump(pw, "  " + prefix);
    }

    static final class AppBroadcastEventsPolicy
            extends BaseAppStateTimeSlotEventsPolicy<AppBroadcastEventsTracker> {
        /**
         * Whether or not we should enable the monitoring on abusive broadcasts.
         */
        static final String KEY_BG_BROADCAST_MONITOR_ENABLED =
                DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "broadcast_monitor_enabled";

        /**
         * The size of the sliding window in which the number of broadcasts is checked
         * against the threshold.
         */
        static final String KEY_BG_BROADCAST_WINDOW =
                DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "broadcast_window";

        /**
         * The threshold at where the number of broadcasts are considered as "excessive"
         * within the given window.
         */
        static final String KEY_BG_EX_BROADCAST_THRESHOLD =
                DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "ex_broadcast_threshold";

        /**
         * Default value to {@link #mTrackerEnabled}.
         */
        static final boolean DEFAULT_BG_BROADCAST_MONITOR_ENABLED = true;

        /**
         * Default value to {@link #mMaxTrackingDuration}.
         */
        static final long DEFAULT_BG_BROADCAST_WINDOW = ONE_DAY;

        /**
         * Default value to {@link #mNumOfEventsThreshold}.
         */
        static final int DEFAULT_BG_EX_BROADCAST_THRESHOLD = 10_000;

        AppBroadcastEventsPolicy(@NonNull Injector injector,
                @NonNull AppBroadcastEventsTracker tracker) {
            super(injector, tracker,
                    KEY_BG_BROADCAST_MONITOR_ENABLED, DEFAULT_BG_BROADCAST_MONITOR_ENABLED,
                    KEY_BG_BROADCAST_WINDOW, DEFAULT_BG_BROADCAST_WINDOW,
                    KEY_BG_EX_BROADCAST_THRESHOLD, DEFAULT_BG_EX_BROADCAST_THRESHOLD);
        }

        @Override
        String getEventName() {
            return "broadcast";
        }

        @Override
        void dump(PrintWriter pw, String prefix) {
            pw.print(prefix);
            pw.println("APP BROADCAST EVENT TRACKER POLICY SETTINGS:");
            super.dump(pw, "  " + prefix);
        }
    }
}
