diff options
8 files changed, 784 insertions, 4 deletions
diff --git a/packages/CarSystemUI/Android.bp b/packages/CarSystemUI/Android.bp index 672879ae6e9d..b2451c91057c 100644 --- a/packages/CarSystemUI/Android.bp +++ b/packages/CarSystemUI/Android.bp @@ -63,6 +63,64 @@ android_library { } +android_library { + name: "CarSystemUI-tests", + manifest: "tests/AndroidManifest.xml", + resource_dirs: [ + "tests/res", + "res-keyguard", + "res", + ], + srcs: [ + "tests/src/**/*.java", + "src/**/*.java", + "src/**/I*.aidl", + ], + static_libs: [ + "SystemUI-tests", + "CarNotificationLib", + "SystemUIPluginLib", + "SystemUISharedLib", + "SettingsLib", + "android.car.userlib", + "androidx.legacy_legacy-support-v4", + "androidx.recyclerview_recyclerview", + "androidx.preference_preference", + "androidx.appcompat_appcompat", + "androidx.mediarouter_mediarouter", + "androidx.palette_palette", + "androidx.legacy_legacy-preference-v14", + "androidx.leanback_leanback", + "androidx.slice_slice-core", + "androidx.slice_slice-view", + "androidx.slice_slice-builders", + "androidx.arch.core_core-runtime", + "androidx.lifecycle_lifecycle-extensions", + "SystemUI-tags", + "SystemUI-proto", + "metrics-helper-lib", + "androidx.test.rules", "hamcrest-library", + "mockito-target-inline-minus-junit4", + "testables", + "truth-prebuilt", + "dagger2-2.19", + "//external/kotlinc:kotlin-annotations", + ], + libs: [ + "android.test.runner", + "telephony-common", + "android.test.base", + "android.car", + ], + + aaptflags: [ + "--extra-packages", + "com.android.systemui", + ], + + plugins: ["dagger2-compiler-2.19"], +} + android_app { name: "CarSystemUI", diff --git a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBarView.java b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBarView.java index 24f8b74eed61..c2455088a52b 100644 --- a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBarView.java +++ b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBarView.java @@ -24,6 +24,7 @@ import android.widget.LinearLayout; import com.android.systemui.Dependency; import com.android.systemui.R; +import com.android.systemui.navigationbar.car.CarNavigationBarController.NotificationsShadeController; import com.android.systemui.statusbar.phone.StatusBarIconController; /** @@ -35,7 +36,7 @@ import com.android.systemui.statusbar.phone.StatusBarIconController; public class CarNavigationBarView extends LinearLayout { private View mNavButtons; private CarNavigationButton mNotificationsButton; - private CarNavigationBarController.NotificationsShadeController mNotificationsShadeController; + private NotificationsShadeController mNotificationsShadeController; private Context mContext; private View mLockScreenButtons; // used to wire in open/close gestures for notifications @@ -81,13 +82,18 @@ public class CarNavigationBarView extends LinearLayout { return super.onInterceptTouchEvent(ev); } - public void setNotificationsPanelController( - CarNavigationBarController.NotificationsShadeController controller) { + /** Sets the notifications panel controller. */ + public void setNotificationsPanelController(NotificationsShadeController controller) { mNotificationsShadeController = controller; } + /** Gets the notifications panel controller. */ + public NotificationsShadeController getNotificationsPanelController() { + return mNotificationsShadeController; + } + /** - * Set a touch listener that will be called from onInterceptTouchEvent and onTouchEvent + * Sets a touch listener that will be called from onInterceptTouchEvent and onTouchEvent * * @param statusBarWindowTouchListener The listener to call from touch and intercept touch */ @@ -95,6 +101,11 @@ public class CarNavigationBarView extends LinearLayout { mStatusBarWindowTouchListener = statusBarWindowTouchListener; } + /** Gets the touch listener that will be called from onInterceptTouchEvent and onTouchEvent. */ + public OnTouchListener getStatusBarWindowTouchListener() { + return mStatusBarWindowTouchListener; + } + @Override public boolean onTouchEvent(MotionEvent event) { if (mStatusBarWindowTouchListener != null) { diff --git a/packages/CarSystemUI/tests/Android.mk b/packages/CarSystemUI/tests/Android.mk new file mode 100644 index 000000000000..1366568c3a66 --- /dev/null +++ b/packages/CarSystemUI/tests/Android.mk @@ -0,0 +1,88 @@ +# Copyright (C) 2019 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. + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_USE_AAPT2 := true +LOCAL_MODULE_TAGS := tests + +LOCAL_JACK_FLAGS := --multi-dex native +LOCAL_DX_FLAGS := --multi-dex + +LOCAL_PACKAGE_NAME := CarSystemUITests +LOCAL_PRIVATE_PLATFORM_APIS := true +LOCAL_COMPATIBILITY_SUITE := device-tests + +LOCAL_STATIC_ANDROID_LIBRARIES := \ + CarSystemUI-tests + +LOCAL_MULTILIB := both + +LOCAL_JNI_SHARED_LIBRARIES := \ + libdexmakerjvmtiagent \ + libmultiplejvmtiagentsinterferenceagent + +LOCAL_JAVA_LIBRARIES := \ + android.test.runner \ + telephony-common \ + android.test.base \ + +LOCAL_AAPT_FLAGS := --extra-packages com.android.systemui + +# sign this with platform cert, so this test is allowed to inject key events into +# UI it doesn't own. This is necessary to allow screenshots to be taken +LOCAL_CERTIFICATE := platform + +# Provide jack a list of classes to exclude from code coverage. +# This is needed because the CarSystemUITests compile CarSystemUI source directly, rather than using +# LOCAL_INSTRUMENTATION_FOR := CarSystemUI. +# +# We want to exclude the test classes from code coverage measurements, but they share the same +# package as the rest of SystemUI so they can't be easily filtered by package name. +# +# Generate a comma separated list of patterns based on the test source files under src/ +# SystemUI classes are in ../src/ so they won't be excluded. +# Example: +# Input files: src/com/android/systemui/Test.java src/com/android/systemui/AnotherTest.java +# Generated exclude list: com.android.systemui.Test*,com.android.systemui.AnotherTest* + +# Filter all src files under src/ to just java files +local_java_files := $(filter %.java,$(call all-java-files-under, src)) + +# Transform java file names into full class names. +# This only works if the class name matches the file name and the directory structure +# matches the package. +local_classes := $(subst /,.,$(patsubst src/%.java,%,$(local_java_files))) +local_comma := , +local_empty := +local_space := $(local_empty) $(local_empty) + +# Convert class name list to jacoco exclude list +# This appends a * to all classes and replace the space separators with commas. +jacoco_exclude := $(subst $(space),$(comma),$(patsubst %,%*,$(local_classes))) + +LOCAL_JACK_COVERAGE_INCLUDE_FILTER := com.android.systemui.*,com.android.keyguard.* +LOCAL_JACK_COVERAGE_EXCLUDE_FILTER := $(jacoco_exclude) + +ifeq ($(EXCLUDE_SYSTEMUI_TESTS),) + include $(BUILD_PACKAGE) +endif + +# Reset variables +local_java_files := +local_classes := +local_comma := +local_space := +jacoco_exclude := diff --git a/packages/CarSystemUI/tests/AndroidManifest.xml b/packages/CarSystemUI/tests/AndroidManifest.xml new file mode 100644 index 000000000000..a74bb56d8d75 --- /dev/null +++ b/packages/CarSystemUI/tests/AndroidManifest.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2019 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. + --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:sharedUserId="android.uid.system" + package="com.android.systemui.tests"> + + <application android:debuggable="true" android:largeHeap="true"> + <uses-library android:name="android.test.runner" /> + + <provider + android:name="androidx.lifecycle.ProcessLifecycleOwnerInitializer" + tools:replace="android:authorities" + android:authorities="${applicationId}.lifecycle-tests" + android:exported="false" + android:enabled="false" + android:multiprocess="true" /> + </application> + + <instrumentation android:name="android.testing.TestableInstrumentation" + android:targetPackage="com.android.systemui.tests" + android:label="Tests for CarSystemUI"> + </instrumentation> +</manifest> diff --git a/packages/CarSystemUI/tests/AndroidTest.xml b/packages/CarSystemUI/tests/AndroidTest.xml new file mode 100644 index 000000000000..8685632f2b63 --- /dev/null +++ b/packages/CarSystemUI/tests/AndroidTest.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2019 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. + --> +<configuration description="Runs Tests for CarSystemUI."> + <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup"> + <option name="test-file-name" value="CarSystemUITests.apk" /> + </target_preparer> + + <option name="test-suite-tag" value="apct" /> + <option name="test-suite-tag" value="framework-base-presubmit" /> + <option name="test-tag" value="CarSystemUITests" /> + <test class="com.android.tradefed.testtype.AndroidJUnitTest" > + <option name="package" value="com.android.systemui.tests" /> + <option name="runner" value="android.testing.TestableInstrumentation" /> + <option name="hidden-api-checks" value="false"/> + </test> +</configuration> diff --git a/packages/CarSystemUI/tests/res/values/config.xml b/packages/CarSystemUI/tests/res/values/config.xml new file mode 100644 index 000000000000..0d08ac26d962 --- /dev/null +++ b/packages/CarSystemUI/tests/res/values/config.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2019 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. + --> +<resources> + <!-- Configure which system ui bars should be displayed. + These can be overwritten within the tests. --> + <bool name="config_enableLeftNavigationBar">false</bool> + <bool name="config_enableRightNavigationBar">false</bool> + <bool name="config_enableBottomNavigationBar">false</bool> +</resources> diff --git a/packages/CarSystemUI/tests/src/com/android/AAAPlusPlusVerifySysuiRequiredTestPropertiesTest.java b/packages/CarSystemUI/tests/src/com/android/AAAPlusPlusVerifySysuiRequiredTestPropertiesTest.java new file mode 100644 index 000000000000..fe59cbf20a13 --- /dev/null +++ b/packages/CarSystemUI/tests/src/com/android/AAAPlusPlusVerifySysuiRequiredTestPropertiesTest.java @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2019 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; + +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +import android.testing.AndroidTestingRunner; +import android.text.TextUtils; +import android.util.Log; + +import androidx.test.filters.LargeTest; +import androidx.test.filters.MediumTest; +import androidx.test.filters.SmallTest; +import androidx.test.internal.runner.ClassPathScanner; +import androidx.test.internal.runner.ClassPathScanner.ChainedClassNameFilter; +import androidx.test.internal.runner.ClassPathScanner.ExternalClassNameFilter; + +import com.android.systemui.SysuiBaseFragmentTest; +import com.android.systemui.SysuiTestCase; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.IOException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +/** + * This is named AAAPlusPlusVerifySysuiRequiredTestPropertiesTest for two reasons. + * a) Its so awesome it deserves an AAA++ + * b) It should run first to draw attention to itself. + * + * For trues though: this test verifies that all the sysui tests extend the right classes. + * This matters because including tests with different context implementations in the same + * test suite causes errors, such as the incorrect settings provider being cached. + * For an example, see {@link com.android.systemui.DependencyTest}. + */ +@RunWith(AndroidTestingRunner.class) +@SmallTest +public class AAAPlusPlusVerifySysuiRequiredTestPropertiesTest extends SysuiTestCase { + + private static final String TAG = "AAA++VerifyTest"; + + private static final Class[] BASE_CLS_WHITELIST = { + SysuiTestCase.class, + SysuiBaseFragmentTest.class, + }; + + private static final Class[] SUPPORTED_SIZES = { + SmallTest.class, + MediumTest.class, + LargeTest.class, + android.test.suitebuilder.annotation.SmallTest.class, + android.test.suitebuilder.annotation.MediumTest.class, + android.test.suitebuilder.annotation.LargeTest.class, + }; + + @Test + public void testAllClassInheritance() throws Throwable { + ArrayList<String> fails = new ArrayList<>(); + for (String className : getClassNamesFromClassPath()) { + Class<?> cls = Class.forName(className, false, this.getClass().getClassLoader()); + if (!isTestClass(cls)) continue; + + boolean hasParent = false; + for (Class<?> parent : BASE_CLS_WHITELIST) { + if (parent.isAssignableFrom(cls)) { + hasParent = true; + break; + } + } + boolean hasSize = hasSize(cls); + if (!hasSize) { + fails.add(cls.getName() + " does not have size annotation, such as @SmallTest"); + } + if (!hasParent) { + fails.add(cls.getName() + " does not extend any of " + getClsStr()); + } + } + + assertThat("All sysui test classes must have size and extend one of " + getClsStr(), + fails, is(empty())); + } + + private boolean hasSize(Class<?> cls) { + for (int i = 0; i < SUPPORTED_SIZES.length; i++) { + if (cls.getDeclaredAnnotation(SUPPORTED_SIZES[i]) != null) return true; + } + return false; + } + + private Collection<String> getClassNamesFromClassPath() { + ClassPathScanner scanner = new ClassPathScanner(mContext.getPackageCodePath()); + + ChainedClassNameFilter filter = new ChainedClassNameFilter(); + + filter.add(new ExternalClassNameFilter()); + filter.add(s -> s.startsWith("com.android.systemui") + || s.startsWith("com.android.keyguard")); + + try { + return scanner.getClassPathEntries(filter); + } catch (IOException e) { + Log.e(TAG, "Failed to scan classes", e); + } + return Collections.emptyList(); + } + + private String getClsStr() { + return TextUtils.join(",", Arrays.asList(BASE_CLS_WHITELIST) + .stream().map(cls -> cls.getSimpleName()).toArray()); + } + + /** + * Determines if given class is a valid test class. + * + * @return <code>true</code> if loadedClass is a test + */ + private boolean isTestClass(Class<?> loadedClass) { + try { + if (Modifier.isAbstract(loadedClass.getModifiers())) { + logDebug(String.format("Skipping abstract class %s: not a test", + loadedClass.getName())); + return false; + } + // TODO: try to find upstream junit calls to replace these checks + if (junit.framework.Test.class.isAssignableFrom(loadedClass)) { + // ensure that if a TestCase, it has at least one test method otherwise + // TestSuite will throw error + if (junit.framework.TestCase.class.isAssignableFrom(loadedClass)) { + return hasJUnit3TestMethod(loadedClass); + } + return true; + } + // TODO: look for a 'suite' method? + if (loadedClass.isAnnotationPresent(RunWith.class)) { + return true; + } + for (Method testMethod : loadedClass.getMethods()) { + if (testMethod.isAnnotationPresent(Test.class)) { + return true; + } + } + logDebug(String.format("Skipping class %s: not a test", loadedClass.getName())); + return false; + } catch (Exception e) { + // Defensively catch exceptions - Will throw runtime exception if it cannot load + // methods. + // For earlier versions of Android (Pre-ICS), Dalvik might try to initialize a class + // during getMethods(), fail to do so, hide the error and throw a NoSuchMethodException. + // Since the java.lang.Class.getMethods does not declare such an exception, resort to a + // generic catch all. + // For ICS+, Dalvik will throw a NoClassDefFoundException. + Log.w(TAG, String.format("%s in isTestClass for %s", e.toString(), + loadedClass.getName())); + return false; + } catch (Error e) { + // defensively catch Errors too + Log.w(TAG, String.format("%s in isTestClass for %s", e.toString(), + loadedClass.getName())); + return false; + } + } + + private boolean hasJUnit3TestMethod(Class<?> loadedClass) { + for (Method testMethod : loadedClass.getMethods()) { + if (isPublicTestMethod(testMethod)) { + return true; + } + } + return false; + } + + // copied from junit.framework.TestSuite + private boolean isPublicTestMethod(Method m) { + return isTestMethod(m) && Modifier.isPublic(m.getModifiers()); + } + + // copied from junit.framework.TestSuite + private boolean isTestMethod(Method m) { + return m.getParameterTypes().length == 0 && m.getName().startsWith("test") + && m.getReturnType().equals(Void.TYPE); + } + + /** + * Utility method for logging debug messages. Only actually logs a message if TAG is marked + * as loggable to limit log spam during normal use. + */ + private void logDebug(String msg) { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, msg); + } + } +} diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/navigationbar/car/CarNavigationBarControllerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/navigationbar/car/CarNavigationBarControllerTest.java new file mode 100644 index 000000000000..20ace44cfa19 --- /dev/null +++ b/packages/CarSystemUI/tests/src/com/android/systemui/navigationbar/car/CarNavigationBarControllerTest.java @@ -0,0 +1,316 @@ +/* + * Copyright (C) 2019 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.navigationbar.car; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; +import android.testing.TestableResources; +import android.view.View; +import android.view.ViewGroup; + +import androidx.test.filters.SmallTest; + +import com.android.systemui.R; +import com.android.systemui.SysuiTestCase; +import com.android.systemui.statusbar.car.hvac.HvacController; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import dagger.Lazy; + +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper +@SmallTest +public class CarNavigationBarControllerTest extends SysuiTestCase { + + private CarNavigationBarController mCarNavigationBar; + private NavigationBarViewFactory mNavigationBarViewFactory; + private Lazy<HvacController> mHvacControllerLazy; + private TestableResources mTestableResources; + + @Mock + private HvacController mHvacController; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + mNavigationBarViewFactory = new NavigationBarViewFactory(mContext); + mHvacControllerLazy = () -> mHvacController; + mTestableResources = mContext.getOrCreateTestableResources(); + } + + @Test + public void testConnectToHvac_callsConnect() { + mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory, + mHvacControllerLazy); + + mCarNavigationBar.connectToHvac(); + + verify(mHvacController).connectToCarService(); + } + + @Test + public void testRemoveAllFromHvac_callsRemoveAll() { + mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory, + mHvacControllerLazy); + + mCarNavigationBar.removeAllFromHvac(); + + verify(mHvacController).removeAllComponents(); + } + + @Test + public void testGetBottomWindow_bottomDisabled_returnsNull() { + mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, false); + mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory, + mHvacControllerLazy); + + ViewGroup window = mCarNavigationBar.getBottomWindow(); + + assertThat(window).isNull(); + } + + @Test + public void testGetBottomWindow_bottomEnabled_returnsWindow() { + mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true); + mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory, + mHvacControllerLazy); + + ViewGroup window = mCarNavigationBar.getBottomWindow(); + + assertThat(window).isNotNull(); + } + + @Test + public void testGetBottomWindow_bottomEnabled_calledTwice_returnsSameWindow() { + mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true); + mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory, + mHvacControllerLazy); + + ViewGroup window1 = mCarNavigationBar.getBottomWindow(); + ViewGroup window2 = mCarNavigationBar.getBottomWindow(); + + assertThat(window1).isEqualTo(window2); + } + + @Test + public void testGetLeftWindow_leftDisabled_returnsNull() { + mTestableResources.addOverride(R.bool.config_enableLeftNavigationBar, false); + mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory, + mHvacControllerLazy); + ViewGroup window = mCarNavigationBar.getLeftWindow(); + assertThat(window).isNull(); + } + + @Test + public void testGetLeftWindow_leftEnabled_returnsWindow() { + mTestableResources.addOverride(R.bool.config_enableLeftNavigationBar, true); + mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory, + mHvacControllerLazy); + + ViewGroup window = mCarNavigationBar.getLeftWindow(); + + assertThat(window).isNotNull(); + } + + @Test + public void testGetLeftWindow_leftEnabled_calledTwice_returnsSameWindow() { + mTestableResources.addOverride(R.bool.config_enableLeftNavigationBar, true); + mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory, + mHvacControllerLazy); + + ViewGroup window1 = mCarNavigationBar.getLeftWindow(); + ViewGroup window2 = mCarNavigationBar.getLeftWindow(); + + assertThat(window1).isEqualTo(window2); + } + + @Test + public void testGetRightWindow_rightDisabled_returnsNull() { + mTestableResources.addOverride(R.bool.config_enableRightNavigationBar, false); + mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory, + mHvacControllerLazy); + + ViewGroup window = mCarNavigationBar.getRightWindow(); + + assertThat(window).isNull(); + } + + @Test + public void testGetRightWindow_rightEnabled_returnsWindow() { + mTestableResources.addOverride(R.bool.config_enableRightNavigationBar, true); + mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory, + mHvacControllerLazy); + + ViewGroup window = mCarNavigationBar.getRightWindow(); + + assertThat(window).isNotNull(); + } + + @Test + public void testGetRightWindow_rightEnabled_calledTwice_returnsSameWindow() { + mTestableResources.addOverride(R.bool.config_enableRightNavigationBar, true); + mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory, + mHvacControllerLazy); + + ViewGroup window1 = mCarNavigationBar.getRightWindow(); + ViewGroup window2 = mCarNavigationBar.getRightWindow(); + + assertThat(window1).isEqualTo(window2); + } + + @Test + public void testSetBottomWindowVisibility_setTrue_isVisible() { + mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true); + mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory, + mHvacControllerLazy); + + ViewGroup window = mCarNavigationBar.getBottomWindow(); + mCarNavigationBar.setBottomWindowVisibility(true); + + assertThat(window.getVisibility()).isEqualTo(View.VISIBLE); + } + + @Test + public void testSetBottomWindowVisibility_setFalse_isGone() { + mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true); + mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory, + mHvacControllerLazy); + + ViewGroup window = mCarNavigationBar.getBottomWindow(); + mCarNavigationBar.setBottomWindowVisibility(false); + + assertThat(window.getVisibility()).isEqualTo(View.GONE); + } + + @Test + public void testSetLeftWindowVisibility_setTrue_isVisible() { + mTestableResources.addOverride(R.bool.config_enableLeftNavigationBar, true); + mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory, + mHvacControllerLazy); + + ViewGroup window = mCarNavigationBar.getLeftWindow(); + mCarNavigationBar.setLeftWindowVisibility(true); + + assertThat(window.getVisibility()).isEqualTo(View.VISIBLE); + } + + @Test + public void testSetLeftWindowVisibility_setFalse_isGone() { + mTestableResources.addOverride(R.bool.config_enableLeftNavigationBar, true); + mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory, + mHvacControllerLazy); + + ViewGroup window = mCarNavigationBar.getLeftWindow(); + mCarNavigationBar.setLeftWindowVisibility(false); + + assertThat(window.getVisibility()).isEqualTo(View.GONE); + } + + @Test + public void testSetRightWindowVisibility_setTrue_isVisible() { + mTestableResources.addOverride(R.bool.config_enableRightNavigationBar, true); + mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory, + mHvacControllerLazy); + + ViewGroup window = mCarNavigationBar.getRightWindow(); + mCarNavigationBar.setRightWindowVisibility(true); + + assertThat(window.getVisibility()).isEqualTo(View.VISIBLE); + } + + @Test + public void testSetRightWindowVisibility_setFalse_isGone() { + mTestableResources.addOverride(R.bool.config_enableRightNavigationBar, true); + mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory, + mHvacControllerLazy); + + ViewGroup window = mCarNavigationBar.getRightWindow(); + mCarNavigationBar.setRightWindowVisibility(false); + + assertThat(window.getVisibility()).isEqualTo(View.GONE); + } + + @Test + public void testRegisterBottomBarTouchListener_createViewFirst_registrationSuccessful() { + mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true); + mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory, + mHvacControllerLazy); + + CarNavigationBarView bottomBar = mCarNavigationBar.getBottomBar(/* isSetUp= */ true); + View.OnTouchListener controller = bottomBar.getStatusBarWindowTouchListener(); + assertThat(controller).isNull(); + mCarNavigationBar.registerBottomBarTouchListener(mock(View.OnTouchListener.class)); + controller = bottomBar.getStatusBarWindowTouchListener(); + + assertThat(controller).isNotNull(); + } + + @Test + public void testRegisterBottomBarTouchListener_registerFirst_registrationSuccessful() { + mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true); + mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory, + mHvacControllerLazy); + + mCarNavigationBar.registerBottomBarTouchListener(mock(View.OnTouchListener.class)); + CarNavigationBarView bottomBar = mCarNavigationBar.getBottomBar(/* isSetUp= */ true); + View.OnTouchListener controller = bottomBar.getStatusBarWindowTouchListener(); + + assertThat(controller).isNotNull(); + } + + @Test + public void testRegisterNotificationController_createViewFirst_registrationSuccessful() { + mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true); + mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory, + mHvacControllerLazy); + + CarNavigationBarView bottomBar = mCarNavigationBar.getBottomBar(/* isSetUp= */ true); + CarNavigationBarController.NotificationsShadeController controller = + bottomBar.getNotificationsPanelController(); + assertThat(controller).isNull(); + mCarNavigationBar.registerNotificationController( + mock(CarNavigationBarController.NotificationsShadeController.class)); + controller = bottomBar.getNotificationsPanelController(); + + assertThat(controller).isNotNull(); + } + + @Test + public void testRegisterNotificationController_registerFirst_registrationSuccessful() { + mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true); + mCarNavigationBar = new CarNavigationBarController(mContext, mNavigationBarViewFactory, + mHvacControllerLazy); + + mCarNavigationBar.registerNotificationController( + mock(CarNavigationBarController.NotificationsShadeController.class)); + CarNavigationBarView bottomBar = mCarNavigationBar.getBottomBar(/* isSetUp= */ true); + CarNavigationBarController.NotificationsShadeController controller = + bottomBar.getNotificationsPanelController(); + + assertThat(controller).isNotNull(); + } +} |