Change Notification Inline Settings for Channels

Removes slider advanced settings.
Move more Guts internals out of BaseStatusBar.

Test: runtest systemui
Change-Id: I0cf7f144859d1248bd54e281cfe0b35a817376a6
diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml
index b03189c..dec8ba6 100644
--- a/packages/SystemUI/tests/AndroidManifest.xml
+++ b/packages/SystemUI/tests/AndroidManifest.xml
@@ -27,6 +27,7 @@
     <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
     <uses-permission android:name="android.permission.BIND_QUICK_SETTINGS_TILE" />
     <uses-permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" />
+    <uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />
 
     <application>
         <uses-library android:name="android.test.runner" />
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationGutsTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationGutsTest.java
new file mode 100644
index 0000000..2cd6dbd
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationGutsTest.java
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2016 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.systemui.statusbar;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.INotificationManager;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.service.notification.StatusBarNotification;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.RadioButton;
+import android.widget.Switch;
+import android.widget.TextView;
+import com.android.systemui.R;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+import org.mockito.Mockito;
+import java.util.Collections;
+import java.util.concurrent.CountDownLatch;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class NotificationGutsTest {
+    private static final String TEST_PACKAGE_NAME = "test_package";
+    private static final String TEST_CHANNEL = "test_channel";
+    private static final String TEST_CHANNEL_NAME = "TEST CHANNEL NAME";
+
+    private NotificationGuts mNotificationGuts;
+    private final INotificationManager mMockINotificationManager = mock(INotificationManager.class);
+    private final PackageManager mMockPackageManager = mock(PackageManager.class);
+    private NotificationChannel mNotificationChannel;
+    private final StatusBarNotification mMockStatusBarNotification =
+            mock(StatusBarNotification.class);
+
+    @Before
+    @UiThreadTest
+    public void setUp() throws Exception {
+        // Inflate the layout
+        final LayoutInflater layoutInflater =
+                LayoutInflater.from(InstrumentationRegistry.getTargetContext());
+        mNotificationGuts = (NotificationGuts) layoutInflater.inflate(R.layout.notification_guts,
+                null);
+
+        // PackageManager must return a packageInfo and applicationInfo.
+        final PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = TEST_PACKAGE_NAME;
+        when(mMockPackageManager.getPackageInfo(anyString(), anyInt())).thenReturn(packageInfo);
+        final ApplicationInfo applicationInfo = new ApplicationInfo();
+        applicationInfo.uid = 1;  // non-zero
+        when(mMockPackageManager.getApplicationInfo(anyString(), anyInt())).thenReturn(
+                applicationInfo);
+
+        // mMockStatusBarNotification with a test channel.
+        mNotificationChannel = new NotificationChannel(
+                TEST_CHANNEL, TEST_CHANNEL_NAME, NotificationManager.IMPORTANCE_LOW);
+        when(mMockStatusBarNotification.getNotificationChannel()).thenReturn(mNotificationChannel);
+        when(mMockStatusBarNotification.getPackageName()).thenReturn(TEST_PACKAGE_NAME);
+    }
+
+    @Test
+    @UiThreadTest
+    public void testBindNotification_SetsTextApplicationName() throws Exception {
+        when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
+        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+                mMockStatusBarNotification, null, null, null);
+        final TextView textView = (TextView) mNotificationGuts.findViewById(R.id.pkgname);
+        assertTrue(textView.getText().toString().contains("App Name"));
+    }
+
+    @Test
+    @UiThreadTest
+    public void testBindNotification_SetsTextChannelName() throws Exception {
+        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+                mMockStatusBarNotification, null, null, null);
+        final TextView textView = (TextView) mNotificationGuts.findViewById(R.id.channel_name);
+        assertEquals(TEST_CHANNEL_NAME, textView.getText());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testBindNotification_SetsOnClickListenerForSettings() throws Exception {
+        final CountDownLatch latch = new CountDownLatch(1);
+        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+                mMockStatusBarNotification, (View v, int appUid) -> { latch.countDown(); },
+                null, null);
+
+        final TextView settingsButton =
+                (TextView) mNotificationGuts.findViewById(R.id.more_settings);
+        settingsButton.performClick();
+        // Verify that listener was triggered.
+        assertEquals(0, latch.getCount());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testBindNotification_SetsOnClickListenerForDone() throws Exception {
+        final CountDownLatch latch = new CountDownLatch(1);
+        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+                mMockStatusBarNotification, null,
+                (View v) -> { latch.countDown(); },
+                null);
+
+        final TextView doneButton = (TextView) mNotificationGuts.findViewById(R.id.done);
+        doneButton.performClick();
+        // Verify that listener was triggered.
+        assertEquals(0, latch.getCount());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testHasImportanceChanged_DefaultsToFalse() throws Exception {
+        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+                mMockStatusBarNotification, null, null, null);
+        assertFalse(mNotificationGuts.hasImportanceChanged());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testHasImportanceChanged_ReturnsTrueAfterButtonChecked() throws Exception {
+        mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
+        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+                mMockStatusBarNotification, null, null, null);
+        // Find the high button and check it.
+        RadioButton highButton = (RadioButton) mNotificationGuts.findViewById(R.id.high_importance);
+        highButton.setChecked(true);
+        assertTrue(mNotificationGuts.hasImportanceChanged());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testImportanceButtonCheckedBasedOnInitialImportance() throws Exception {
+        mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_HIGH);
+        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+                mMockStatusBarNotification, null, null, null);
+
+        RadioButton highButton = (RadioButton) mNotificationGuts.findViewById(R.id.high_importance);
+        assertTrue(highButton.isChecked());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testBindNotification_DoesNotUpdateNotificationChannel() throws Exception {
+        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+                mMockStatusBarNotification, null, null, null);
+        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+                anyString(), anyInt(), any());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testDoesNotUpdateNotificationChannelAfterImportanceChanged() throws Exception {
+        mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
+        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+                mMockStatusBarNotification, null, null, null);
+
+        RadioButton highButton = (RadioButton) mNotificationGuts.findViewById(R.id.high_importance);
+        highButton.setChecked(true);
+        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+                anyString(), anyInt(), any());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testCloseControls_DoesNotUpdateNotificationChannelIfUnchanged() throws Exception {
+        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+                mMockStatusBarNotification, null, null, null);
+
+        mNotificationGuts.closeControls(-1, -1, true);
+        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+                anyString(), anyInt(), any());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testCloseControls_CallsUpdateNotificationChannelIfChanged() throws Exception {
+        mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
+        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+                mMockStatusBarNotification, null, null, null);
+
+        RadioButton highButton = (RadioButton) mNotificationGuts.findViewById(R.id.high_importance);
+        highButton.setChecked(true);
+        mNotificationGuts.closeControls(-1, -1, true);
+        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+                eq(TEST_PACKAGE_NAME), anyInt(), eq(mNotificationChannel));
+        assertEquals(NotificationManager.IMPORTANCE_HIGH, mNotificationChannel.getImportance());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testCloseControls_DoesNotUpdateNotificationChannelIfSaveFalse() throws Exception {
+        mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
+        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+                mMockStatusBarNotification, null, null, null);
+
+        RadioButton highButton = (RadioButton) mNotificationGuts.findViewById(R.id.high_importance);
+        highButton.setChecked(true);
+        mNotificationGuts.closeControls(-1, -1, false);
+        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+                anyString(), anyInt(), any());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testEnabledSwitchOnByDefault() throws Exception {
+        mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
+        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+                mMockStatusBarNotification, null, null, null);
+
+        Switch enabledSwitch = (Switch) mNotificationGuts.findViewById(R.id.channel_enabled_switch);
+        assertTrue(enabledSwitch.isChecked());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testEnabledSwitchVisibleByDefault() throws Exception {
+        mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
+        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+                mMockStatusBarNotification, null, null, null);
+
+        Switch enabledSwitch = (Switch) mNotificationGuts.findViewById(R.id.channel_enabled_switch);
+        assertEquals(View.VISIBLE, enabledSwitch.getVisibility());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testEnabledSwitchInvisibleIfNonBlockable() throws Exception {
+        mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
+        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+                mMockStatusBarNotification, null, null, Collections.singleton(TEST_PACKAGE_NAME));
+
+        Switch enabledSwitch = (Switch) mNotificationGuts.findViewById(R.id.channel_enabled_switch);
+        assertEquals(View.INVISIBLE, enabledSwitch.getVisibility());
+    }
+
+    @Test
+    @UiThreadTest
+    public void testEnabledSwitchChangedCallsUpdateNotificationChannel() throws Exception {
+        mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
+        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+                mMockStatusBarNotification, null, null, Collections.singleton(TEST_PACKAGE_NAME));
+
+        Switch enabledSwitch = (Switch) mNotificationGuts.findViewById(R.id.channel_enabled_switch);
+        enabledSwitch.setChecked(false);
+        mNotificationGuts.closeControls(-1, -1, true);
+        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+                eq(TEST_PACKAGE_NAME), anyInt(), eq(mNotificationChannel));
+    }
+
+    @Test
+    @UiThreadTest
+    public void testEnabledSwitchOverridesOtherButtons() throws Exception {
+        mNotificationChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
+        mNotificationGuts.bindNotification(mMockPackageManager, mMockINotificationManager,
+                mMockStatusBarNotification, null, null, null);
+
+        Switch enabledSwitch = (Switch) mNotificationGuts.findViewById(R.id.channel_enabled_switch);
+        RadioButton lowButton = (RadioButton) mNotificationGuts.findViewById(R.id.low_importance);
+        lowButton.setChecked(true);
+        enabledSwitch.setChecked(false);
+        mNotificationGuts.closeControls(-1, -1, true);
+        assertEquals(NotificationManager.IMPORTANCE_NONE, mNotificationChannel.getImportance());
+    }
+}