/*
 * 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")
    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,
                            Context.RECEIVER_EXPORTED_UNAUDITED);
                },
                (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")
    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();
        }
    }
}
