/*
 * 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 android.app.notification.legacy.cts;

import static android.Manifest.permission.POST_NOTIFICATIONS;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;

import static junit.framework.Assert.assertEquals;

import static org.junit.Assert.assertTrue;

import android.app.Instrumentation;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.UiAutomation;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.ParcelFileDescriptor;
import android.provider.Telephony.Threads;
import android.service.notification.NotificationListenerService;

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

import junit.framework.Assert;

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

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * Home for tests that need to verify behavior for apps that target old sdk versions.
 */
@RunWith(AndroidJUnit4.class)
public class LegacyNotificationManagerTest {
    final String TAG = "LegacyNoManTest";

    final String NOTIFICATION_CHANNEL_ID = "LegacyNotificationManagerTest";
    private NotificationManager mNotificationManager;
    private Context mContext;

    private SecondaryNotificationListener mSecondaryListener;
    private TestNotificationListener mListener;

    @Before
    public void setUp() throws Exception {
        mContext = InstrumentationRegistry.getContext();
        InstrumentationRegistry.getInstrumentation().getUiAutomation()
                .adoptShellPermissionIdentity(POST_NOTIFICATIONS);
        toggleListenerAccess(TestNotificationListener.getId(),
                InstrumentationRegistry.getInstrumentation(), false);
        toggleListenerAccess(SecondaryNotificationListener.getId(),
                InstrumentationRegistry.getInstrumentation(), false);
        mNotificationManager = (NotificationManager) mContext.getSystemService(
                Context.NOTIFICATION_SERVICE);
        mNotificationManager.createNotificationChannel(new NotificationChannel(
                NOTIFICATION_CHANNEL_ID, "name", NotificationManager.IMPORTANCE_DEFAULT));
    }

    @After
    public void tearDown() throws Exception {
        InstrumentationRegistry.getInstrumentation().getUiAutomation()
                .dropShellPermissionIdentity();
        toggleListenerAccess(TestNotificationListener.getId(),
                InstrumentationRegistry.getInstrumentation(), false);
        toggleListenerAccess(SecondaryNotificationListener.getId(),
                InstrumentationRegistry.getInstrumentation(), false);
        Thread.sleep(500); // wait for listener to disconnect
        assertTrue(mListener == null || !mListener.isConnected);
        assertTrue(mSecondaryListener == null || !mSecondaryListener.isConnected);
    }

    @Test
    public void testPrePCannotToggleAlarmsAndMediaTest() throws Exception {
        toggleNotificationPolicyAccess(mContext.getPackageName(),
                InstrumentationRegistry.getInstrumentation(), true);

        // Pre-P cannot toggle alarms and media
        NotificationManager.Policy origPolicy = mNotificationManager.getNotificationPolicy();
        int alarmBit = origPolicy.priorityCategories & NotificationManager.Policy
                .PRIORITY_CATEGORY_ALARMS;
        int mediaBit = origPolicy.priorityCategories & NotificationManager.Policy
                .PRIORITY_CATEGORY_MEDIA;
        int systemBit = origPolicy.priorityCategories & NotificationManager.Policy
                .PRIORITY_CATEGORY_SYSTEM;

        // attempt to toggle off alarms, media, system:
        mNotificationManager.setNotificationPolicy(new NotificationManager.Policy(0, 0, 0));
        NotificationManager.Policy policy = mNotificationManager.getNotificationPolicy();
        assertEquals(alarmBit, policy.priorityCategories
                & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS);
        assertEquals(mediaBit, policy.priorityCategories
                & NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA);
        assertEquals(systemBit, policy.priorityCategories
                & NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM);

        // attempt to toggle on alarms, media, system:
        mNotificationManager.setNotificationPolicy(new NotificationManager.Policy(
                NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS
                        | NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA, 0, 0));
        policy = mNotificationManager.getNotificationPolicy();
        assertEquals(alarmBit, policy.priorityCategories
                & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS);
        assertEquals(mediaBit, policy.priorityCategories
                & NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA);
        assertEquals(systemBit, policy.priorityCategories
                & NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM);

        toggleNotificationPolicyAccess(mContext.getPackageName(),
                InstrumentationRegistry.getInstrumentation(), false);
    }

    @Test
    public void testSetNotificationPolicy_preP_setOldFields() throws Exception {
        toggleNotificationPolicyAccess(mContext.getPackageName(),
                InstrumentationRegistry.getInstrumentation(), true);

        NotificationManager.Policy userPolicy = mNotificationManager.getNotificationPolicy();

        NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
                SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
        mNotificationManager.setNotificationPolicy(appPolicy);

        int expected = userPolicy.suppressedVisualEffects
                | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
                | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_LIGHTS
                | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;

        assertEquals(expected,
                mNotificationManager.getNotificationPolicy().suppressedVisualEffects);
    }

    @Test
    public void testSetNotificationPolicy_preP_setNewFields() throws Exception {
        toggleNotificationPolicyAccess(mContext.getPackageName(),
                InstrumentationRegistry.getInstrumentation(), true);

        NotificationManager.Policy userPolicy = mNotificationManager.getNotificationPolicy();

        NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
                SUPPRESSED_EFFECT_NOTIFICATION_LIST);
        mNotificationManager.setNotificationPolicy(appPolicy);

        int expected = userPolicy.suppressedVisualEffects;
        expected &= ~ SUPPRESSED_EFFECT_SCREEN_OFF & ~ SUPPRESSED_EFFECT_SCREEN_ON;
        assertEquals(expected,
                mNotificationManager.getNotificationPolicy().suppressedVisualEffects);

        toggleNotificationPolicyAccess(mContext.getPackageName(),
                InstrumentationRegistry.getInstrumentation(), false);
    }

    @Test
    public void testSuspendPackage() throws Exception {
        toggleListenerAccess(TestNotificationListener.getId(),
                InstrumentationRegistry.getInstrumentation(), true);
        Thread.sleep(1000); // wait for listener to be allowed

        mListener = TestNotificationListener.getInstance();
        Assert.assertNotNull(mListener);

        sendNotification(1, R.drawable.icon_black);
        assertTrue(pollForPostedNotifications(1));
        mListener.resetData();

        // suspend package, listener receives onRemoved
        suspendPackage(mContext.getPackageName(), InstrumentationRegistry.getInstrumentation(),
                true);
        Thread.sleep(1000); // wait for notification listener to get response
        assertTrue(pollForRemovedNotifications(1));

        // unsuspend package, listener receives onPosted
        suspendPackage(mContext.getPackageName(), InstrumentationRegistry.getInstrumentation(),
                false);
        assertTrue(pollForPostedNotifications(1));

        toggleListenerAccess(TestNotificationListener.getId(),
                InstrumentationRegistry.getInstrumentation(), false);

        mListener.resetData();
    }

    @Test
    public void testSuspendedPackageSendNotification() throws Exception {
        toggleListenerAccess(TestNotificationListener.getId(),
                InstrumentationRegistry.getInstrumentation(), true);
        Thread.sleep(500); // wait for listener to be allowed

        mListener = TestNotificationListener.getInstance();
        Assert.assertNotNull(mListener);

        // suspend package
        suspendPackage(mContext.getPackageName(), InstrumentationRegistry.getInstrumentation(),
                true);
        Thread.sleep(500); // wait for notification listener to get response

        sendNotification(1, R.drawable.icon_black);
        Thread.sleep(1000); // wait for notification listener in case it receives notification
        assertEquals(0, mListener.mPosted.size()); // shouldn't see any notifications posted

        // unsuspend package, listener should receive onPosted
        suspendPackage(mContext.getPackageName(), InstrumentationRegistry.getInstrumentation(),
                false);
        assertTrue(pollForPostedNotifications(1));

        toggleListenerAccess(TestNotificationListener.getId(),
                InstrumentationRegistry.getInstrumentation(), false);

        mListener.resetData();
    }

    @Test
    public void testResetListenerHints_singleListener() throws Exception {
      int conditionValue = 0;
      int condition = NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS;

      toggleListenerAccess(
          TestNotificationListener.getId(), InstrumentationRegistry.getInstrumentation(), true);
      Thread.sleep(500); // wait for listener to be allowed

      mListener = TestNotificationListener.getInstance();
      Assert.assertNotNull(mListener);
      /*In case of wear os we have some default disable listener registered*/
      if (isWatch()) {
        condition |= NotificationListenerService.HINT_HOST_DISABLE_NOTIFICATION_EFFECTS;
        conditionValue = mListener.getCurrentListenerHints();
      }

      mListener.requestListenerHints(NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS);

      assertEquals(condition, mListener.getCurrentListenerHints());

      mListener.clearRequestedListenerHints();

      assertEquals(conditionValue, mListener.getCurrentListenerHints());
    }

    @Test
    public void testResetListenerHints_multiListener() throws Exception {
        toggleListenerAccess(TestNotificationListener.getId(),
                InstrumentationRegistry.getInstrumentation(), true);
        toggleListenerAccess(SecondaryNotificationListener.getId(),
                InstrumentationRegistry.getInstrumentation(), true);
        Thread.sleep(500); // wait for listener to be allowed

        mListener = TestNotificationListener.getInstance();
        mSecondaryListener = SecondaryNotificationListener.getInstance();
        Assert.assertNotNull(mListener);
        Assert.assertNotNull(mSecondaryListener);

        mListener.requestListenerHints(NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS);
        mSecondaryListener.requestListenerHints(
                NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS
                        | NotificationListenerService.HINT_HOST_DISABLE_NOTIFICATION_EFFECTS);

        assertEquals(NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS
                | NotificationListenerService.HINT_HOST_DISABLE_NOTIFICATION_EFFECTS,
                mListener.getCurrentListenerHints());

        mSecondaryListener.clearRequestedListenerHints();
        /*In case of wear os we have some default disable listener registered*/
        if (!isWatch()) {
          assertEquals(NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS,
              mSecondaryListener.getCurrentListenerHints());
        }
    }

    @Test
    public void testSetNotificationPolicy_preP_setOldNewFields() throws Exception {
        toggleNotificationPolicyAccess(mContext.getPackageName(),
                InstrumentationRegistry.getInstrumentation(), true);

        NotificationManager.Policy userPolicy = mNotificationManager.getNotificationPolicy();

        NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
                SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
        mNotificationManager.setNotificationPolicy(appPolicy);

        int expected = userPolicy.suppressedVisualEffects
                | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_PEEK;
        expected &= ~ SUPPRESSED_EFFECT_SCREEN_OFF;
        assertEquals(expected,
                mNotificationManager.getNotificationPolicy().suppressedVisualEffects);

        toggleNotificationPolicyAccess(mContext.getPackageName(),
                InstrumentationRegistry.getInstrumentation(), false);
    }

    @Test
    public void testChannelDeletion_cancelReason() throws Exception {
        assertEquals(Build.VERSION_CODES.O_MR1, mContext.getApplicationInfo().targetSdkVersion);
        toggleListenerAccess(TestNotificationListener.getId(),
                InstrumentationRegistry.getInstrumentation(), true);
        Thread.sleep(1000); // wait for listener to be allowed
        mListener = TestNotificationListener.getInstance();

        sendNotification(566, R.drawable.icon_black);

        // wait for notification listener to receive notification
        assertTrue(pollForPostedNotifications(1));
        String key = mListener.mPosted.get(0).getKey();

        mNotificationManager.deleteNotificationChannel(NOTIFICATION_CHANNEL_ID);

        assertEquals(NotificationListenerService.REASON_CHANNEL_BANNED,
                getCancellationReason(key));
    }

    private void sendNotification(final int id, final int icon) throws Exception {
        sendNotification(id, null, icon);
    }

    private void sendNotification(final int id, String groupKey, final int icon) throws Exception {
        final Intent intent = new Intent(Intent.ACTION_MAIN, Threads.CONTENT_URI);

        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP
                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
        intent.setAction(Intent.ACTION_MAIN);

        final PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
        final Notification notification =
                new Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
                        .setSmallIcon(icon)
                        .setWhen(System.currentTimeMillis())
                        .setContentTitle("notify#" + id)
                        .setContentText("This is #" + id + "notification  ")
                        .setContentIntent(pendingIntent)
                        .setGroup(groupKey)
                        .build();
        mNotificationManager.notify(id, notification);
    }

    // Wait for the listener to have received the specified number of posted notifications.
    private boolean pollForPostedNotifications(int expected) {
        for (int tries = 5; tries-- > 0; ) {
            if (mListener.mPosted.size() >= expected) {
                return true;
            }
            try {
                Thread.sleep(2000);
            } catch (InterruptedException ex) {
                // pass
            }
        }
        return false;
    }

    // Wait for the listener to have received the specified number of removed notifications.
    private boolean pollForRemovedNotifications(int expected) {
        for (int tries = 5; tries-- > 0; ) {
            if (mListener.mRemoved.size() >= expected) {
                return true;
            }
            try {
                Thread.sleep(2000);
            } catch (InterruptedException ex) {
                // pass
            }
        }
        return false;
    }

    private int getCancellationReason(String key) {
        for (int tries = 3; tries-- > 0; ) {
            if (mListener.mRemoved.containsKey(key)) {
                return mListener.mRemoved.get(key);
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ex) {
                // pass
            }
        }
        return -1;
    }

    private void toggleNotificationPolicyAccess(String packageName,
            Instrumentation instrumentation, boolean on) throws IOException {

        String command = " cmd notification"
                       + " " + (on ? "allow_dnd" : "disallow_dnd")
                       + " " + packageName
                       + " " + mContext.getUserId();

        runCommand(command, instrumentation);

        NotificationManager nm = mContext.getSystemService(NotificationManager.class);
        Assert.assertEquals("Notification Policy Access Grant is " +
                        nm.isNotificationPolicyAccessGranted() + " not " + on, on,
                nm.isNotificationPolicyAccessGranted());
    }

    private void suspendPackage(String packageName,
            Instrumentation instrumentation, boolean suspend) throws IOException {
        String command = " cmd package"
                       + " " + (suspend ? "suspend" : "unsuspend")
                       + " --user " + mContext.getUserId()
                       + " " + packageName;

        runCommand(command, instrumentation);
    }

    private void toggleListenerAccess(String componentName, Instrumentation instrumentation,
            boolean on) throws IOException {

        String command = " cmd notification"
                       + " " + (on ? "allow_listener" : "disallow_listener")
                       + " " + componentName
                       + " " + mContext.getUserId();

        runCommand(command, instrumentation);

        final NotificationManager nm = mContext.getSystemService(NotificationManager.class);
        final ComponentName listenerComponent = TestNotificationListener.getComponentName();
        Assert.assertTrue(listenerComponent + " has not been granted access",
                nm.isNotificationListenerAccessGranted(listenerComponent) == on);
    }

    private void runCommand(String command, Instrumentation instrumentation) throws IOException {
        UiAutomation uiAutomation = instrumentation.getUiAutomation();
        // Execute command
        try (ParcelFileDescriptor fd = uiAutomation.executeShellCommand(command)) {
            Assert.assertNotNull("Failed to execute shell command: " + command, fd);
            // Wait for the command to finish by reading until EOF
            try (InputStream in = new FileInputStream(fd.getFileDescriptor())) {
                byte[] buffer = new byte[4096];
                while (in.read(buffer) > 0) {}
            } catch (IOException e) {
                throw new IOException("Could not read stdout of command: " + command, e);
            }
        } finally {
            uiAutomation.destroy();
        }
    }

    private boolean isWatch() {
      return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
    }
}
