/*
 * Copyright (C) 2017 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 android.app.cts.backgroundrestrictions;

import static junit.framework.Assert.assertFalse;

import static org.junit.Assert.assertTrue;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.platform.test.annotations.AppModeFull;
import android.util.Log;

import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;

import com.android.compatibility.common.util.AmUtils;
import com.android.compatibility.common.util.CddTest;
import com.android.compatibility.common.util.SystemUtil;

import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

@RunWith(AndroidJUnit4.class)
public class BroadcastsTest {
    private static final String TAG = "BroadcastsTest";

    private final int BROADCASTS_TIMEOUT_SECOND = 3 * 60;

    private static Context getContext() {
        return InstrumentationRegistry.getContext();
    }

    /**
     * Make sure "com.android.launcher.action.INSTALL_SHORTCUT" won't be delivered to a runtime
     * receiver.
     */
    @Test
    @CddTest(requirement="3.5/C-0-6,3.2.3.4/C-0-1")
    public void testNonSupportedBroadcastsNotDelivered_runtimeReceiver() throws Exception {

        // Need a reference here to initialize it in a lambda.
        final AtomicReference<BroadcastReceiver> receiverRef = new AtomicReference<>();

        testNonSupportedBroadcastsNotDelivered(
                (filter, callback) -> {
                    final BroadcastReceiver receiver = new BroadcastReceiver() {
                        @Override
                        public void onReceive(Context context, Intent intent) {
                            callback.accept(intent);
                        }
                    };
                    receiverRef.set(receiver);

                    getContext().registerReceiver(receiver, filter);
                },
                (intent) -> {},
                () -> getContext().unregisterReceiver(receiverRef.get()));
    }

    /**
     * Make sure "com.android.launcher.action.INSTALL_SHORTCUT" won't be delivered to a manifest
     * receiver, even if an intent is targeted to the component.
     */
    @AppModeFull(reason = "Instant apps don't get to run in the background.")
    @Test
    @CddTest(requirement="3.5/C-0-6,3.2.3.4/C-0-1")
    public void testNonSupportedBroadcastsNotDelivered_manifestReceiver() throws Exception {
        // Need a reference here to initialize it in a lambda.
        final AtomicReference<BroadcastReceiver> receiverRef = new AtomicReference<>();

        testNonSupportedBroadcastsNotDelivered(
                (filter, callback) -> {
                    MyReceiver.setCallback((intent) -> callback.accept(intent));
                },
                (intent) -> intent.setComponent(MyReceiver.getComponent()),
                () -> MyReceiver.clearCallback());
    }

    private void testNonSupportedBroadcastsNotDelivered(
            BiConsumer<IntentFilter, Consumer<Intent>> receiverInitializer,
            Consumer<Intent> intentInitializer,
            Runnable receiverDeinitializer) throws Exception {

        AmUtils.waitForBroadcastIdle();

        // This broadcast should not be delivered.
        final String[] UNSUPPORTED_BROADCASTS = new String[]{
                "com.android.launcher.action.INSTALL_SHORTCUT",
        };
        // These broadcasts should be delivered.
        final String[] SUPPORTED_BROADCASTS = new String[]{
                Intent.ACTION_VIEW,
                Intent.ACTION_SEND,
        };
        final String[][] ALL_BROADCASTS = new String[][]{
                UNSUPPORTED_BROADCASTS,
                SUPPORTED_BROADCASTS,
        };

        // GuardedBy receivedBroadcasts
        final ArrayList<String> receivedBroadcasts = new ArrayList<>();

        final CountDownLatch latch = new CountDownLatch(SUPPORTED_BROADCASTS.length);

        // Register a receiver for all the actions.
        final IntentFilter filter = new IntentFilter();
        for (String[] list : ALL_BROADCASTS) {
            for (String action : list) {
                filter.addAction(action);
            }
        }

        // This is what's called when a receiver receives an intent.
        final Consumer<Intent> callbackHandler = (intent) -> {
            Log.i(TAG, "Intent " + intent + " received.");
            synchronized (receivedBroadcasts) {
                receivedBroadcasts.add(intent.getAction());
            }

            latch.countDown();
        };

        receiverInitializer.accept(filter, callbackHandler);
        try {
            // Send all broadcasts one by one.
            for (String[] list : ALL_BROADCASTS) {
                for (String action : list) {
                    final Intent intent = new Intent(action)
                        .setFlags(Intent.FLAG_RECEIVER_FOREGROUND);

                    intentInitializer.accept(intent);

                    getContext().sendBroadcast(intent);
                }
            }
            assertTrue(latch.await(BROADCASTS_TIMEOUT_SECOND, TimeUnit.SECONDS));

            final String history =
                    SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(),
                    "dumpsys activity broadcasts history");
            Log.v(TAG, "Broadcast history:\n");
            for (String line : history.split("\n")) {
                Log.v(TAG, line);
            }


            // Verify the received lists.
            // The supported ones should be delivered, and show up in the history.
            // The unsupported should not.
            synchronized (receivedBroadcasts) {
                for (String action : SUPPORTED_BROADCASTS) {
                    assertTrue(receivedBroadcasts.contains(action));
                    assertTrue(history.contains(action));
                }

                for (String action : UNSUPPORTED_BROADCASTS) {
                    assertFalse(receivedBroadcasts.contains(action));
                    assertFalse(history.contains(action));
                }
            }

        } finally {
            receiverDeinitializer.run();
        }
    }
}
