Add tests for CarUi class and add FPV to shared lib
Fixes: 190782532
Fixes: 189866049
Test: ./gradlew createDebugCoverageReport
Change-Id: I38757254872456fe17fbc227d9ab9fb81b3f887a
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/AndroidManifest.xml b/car-ui-lib/car-ui-lib/src/androidTest/AndroidManifest.xml
index 675f5bc..21c8813 100644
--- a/car-ui-lib/car-ui-lib/src/androidTest/AndroidManifest.xml
+++ b/car-ui-lib/car-ui-lib/src/androidTest/AndroidManifest.xml
@@ -18,6 +18,8 @@
package="com.android.car.ui.test">
<application android:debuggable="true" android:theme="@style/Theme.CarUi.NoToolbar">
<uses-library android:name="android.test.runner" />
+ <activity android:name="com.android.car.ui.TrulyEmptyActivity"
+ android:theme="@android:style/Theme.Material.NoActionBar"/>
<activity android:name="com.android.car.ui.TestActivity" />
<activity android:name="com.android.car.ui.recyclerview.CarUiRecyclerViewTestActivity" />
<activity android:name="com.android.car.ui.imewidescreen.CarUiImeWideScreenTestActivity" />
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/TrulyEmptyActivity.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/TrulyEmptyActivity.java
new file mode 100644
index 0000000..6085f6c
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/TrulyEmptyActivity.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2021 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.car.ui;
+
+import android.app.Activity;
+
+/**
+ * An empty activity used for testing
+ */
+public class TrulyEmptyActivity extends Activity {
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/core/CarUiTest.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/core/CarUiTest.java
new file mode 100644
index 0000000..34b082a
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/core/CarUiTest.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 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.car.ui.core;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
+
+import com.android.car.ui.test.R;
+
+import org.junit.Test;
+
+/** A test for {@link com.android.car.ui.core.CarUi} */
+public class CarUiTest {
+
+ @Test
+ public void test_findCarUiComponentById_returnsNullWithNullInput() {
+ assertNull(CarUi.findCarUiComponentById(null, R.id.car_ui_recycler_view));
+ }
+
+ @Test
+ public void test_requireCarUiComponentById_throwsWithNullInput() {
+ assertThrows(NullPointerException.class,
+ () -> CarUi.requireCarUiComponentById(null, R.id.car_ui_recycler_view));
+ }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/toolbar/EmptyToolbarController.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/toolbar/EmptyToolbarController.java
new file mode 100644
index 0000000..a984e14
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/toolbar/EmptyToolbarController.java
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2021 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.car.ui.toolbar;
+
+import android.graphics.drawable.Drawable;
+import android.view.View;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.car.ui.imewidescreen.CarUiImeSearchListItem;
+
+import java.util.List;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+/**
+ * A class that implements ToolbarController but does nothing, just to easily get a non-null
+ * ToolbarController
+ */
+public class EmptyToolbarController implements ToolbarController {
+ @Override
+ public void setTitle(int title) {
+
+ }
+
+ @Override
+ public void setTitle(CharSequence title) {
+
+ }
+
+ @Override
+ public CharSequence getTitle() {
+ return null;
+ }
+
+ @Override
+ public void setSubtitle(int title) {
+
+ }
+
+ @Override
+ public void setSubtitle(CharSequence title) {
+
+ }
+
+ @Override
+ public CharSequence getSubtitle() {
+ return null;
+ }
+
+ @Override
+ public void setTabs(@Nullable List<Tab> tabs) {
+
+ }
+
+ @Override
+ public void setTabs(@Nullable List<Tab> tabs,
+ int selectedTab) {
+
+ }
+
+ @Override
+ public List<Tab> getTabs() {
+ return null;
+ }
+
+ @Override
+ public int getTabCount() {
+ return 0;
+ }
+
+ @Override
+ public int getTabPosition(TabLayout.Tab tab) {
+ return 0;
+ }
+
+ @Override
+ public void addTab(TabLayout.Tab tab) {
+
+ }
+
+ @Override
+ public void clearAllTabs() {
+
+ }
+
+ @Override
+ public TabLayout.Tab getTab(int position) {
+ return null;
+ }
+
+ @Override
+ public void selectTab(int position) {
+
+ }
+
+ @Override
+ public int getSelectedTab() {
+ return 0;
+ }
+
+ @Override
+ public void setShowTabsInSubpage(boolean showTabs) {
+
+ }
+
+ @Override
+ public boolean getShowTabsInSubpage() {
+ return false;
+ }
+
+ @Override
+ public void setLogo(int resId) {
+
+ }
+
+ @Override
+ public void setLogo(Drawable drawable) {
+
+ }
+
+ @Override
+ public void setSearchHint(int resId) {
+
+ }
+
+ @Override
+ public void setSearchHint(CharSequence hint) {
+
+ }
+
+ @Override
+ public CharSequence getSearchHint() {
+ return null;
+ }
+
+ @Override
+ public void setSearchIcon(int resId) {
+
+ }
+
+ @Override
+ public void setSearchIcon(Drawable d) {
+
+ }
+
+ @Override
+ public void setSearchMode(SearchMode mode) {
+
+ }
+
+ @Override
+ public void setNavButtonMode(Toolbar.NavButtonMode style) {
+
+ }
+
+ @Override
+ public void setNavButtonMode(NavButtonMode mode) {
+
+ }
+
+ @Override
+ public Toolbar.NavButtonMode getNavButtonMode() {
+ return null;
+ }
+
+ @Override
+ public void setBackgroundShown(boolean shown) {
+
+ }
+
+ @Override
+ public boolean getBackgroundShown() {
+ return false;
+ }
+
+ @Override
+ public void setMenuItems(@Nullable List<MenuItem> items) {
+
+ }
+
+ @Override
+ public List<MenuItem> setMenuItems(int resId) {
+ return null;
+ }
+
+ @NonNull
+ @Override
+ public List<MenuItem> getMenuItems() {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public MenuItem findMenuItemById(int id) {
+ return null;
+ }
+
+ @NonNull
+ @Override
+ public MenuItem requireMenuItemById(int id) {
+ return null;
+ }
+
+ @Override
+ public void setShowMenuItemsWhileSearching(boolean showMenuItems) {
+
+ }
+
+ @Override
+ public boolean getShowMenuItemsWhileSearching() {
+ return false;
+ }
+
+ @Override
+ public void setSearchQuery(String query) {
+
+ }
+
+ @Override
+ public void setState(Toolbar.State state) {
+
+ }
+
+ @Override
+ public Toolbar.State getState() {
+ return null;
+ }
+
+ @Override
+ public boolean isStateSet() {
+ return false;
+ }
+
+ @Override
+ public void registerOnTabSelectedListener(Toolbar.OnTabSelectedListener listener) {
+
+ }
+
+ @Override
+ public boolean unregisterOnTabSelectedListener(Toolbar.OnTabSelectedListener listener) {
+ return false;
+ }
+
+ @Override
+ public void registerOnSearchListener(Toolbar.OnSearchListener listener) {
+
+ }
+
+ @Override
+ public boolean unregisterOnSearchListener(Toolbar.OnSearchListener listener) {
+ return false;
+ }
+
+ @Override
+ public void registerSearchListener(Consumer<String> listener) {
+
+ }
+
+ @Override
+ public boolean unregisterSearchListener(Consumer<String> listener) {
+ return false;
+ }
+
+ @Override
+ public void setSearchConfig(@Nullable SearchConfig searchConfig) {
+
+ }
+
+ @Override
+ public SearchCapabilities getSearchCapabilities() {
+ return null;
+ }
+
+ @Override
+ public boolean canShowSearchResultItems() {
+ return false;
+ }
+
+ @Override
+ public boolean canShowSearchResultsView() {
+ return false;
+ }
+
+ @Override
+ public void setSearchResultsView(@Nullable View view) {
+
+ }
+
+ @Override
+ public void setSearchResultsInputViewIcon(@NonNull Drawable drawable) {
+
+ }
+
+ @Override
+ public void setSearchResultItems(List<? extends CarUiImeSearchListItem> searchItems) {
+
+ }
+
+ @Override
+ public void registerOnSearchCompletedListener(Toolbar.OnSearchCompletedListener listener) {
+
+ }
+
+ @Override
+ public boolean unregisterOnSearchCompletedListener(Toolbar.OnSearchCompletedListener listener) {
+ return false;
+ }
+
+ @Override
+ public void registerSearchCompletedListener(Runnable listener) {
+
+ }
+
+ @Override
+ public boolean unregisterSearchCompletedListener(Runnable listener) {
+ return false;
+ }
+
+ @Override
+ public void registerOnBackListener(Toolbar.OnBackListener listener) {
+
+ }
+
+ @Override
+ public boolean unregisterOnBackListener(Toolbar.OnBackListener listener) {
+ return false;
+ }
+
+ @Override
+ public void registerBackListener(Supplier<Boolean> listener) {
+
+ }
+
+ @Override
+ public boolean unregisterBackListener(Supplier<Boolean> listener) {
+ return false;
+ }
+
+ @Override
+ public ProgressBarController getProgressBar() {
+ return null;
+ }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/toolbar/InstallBaseLayoutAroundTest.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/toolbar/InstallBaseLayoutAroundTest.java
new file mode 100644
index 0000000..a09357e
--- /dev/null
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/toolbar/InstallBaseLayoutAroundTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2021 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.car.ui.toolbar;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+
+import androidx.test.ext.junit.rules.ActivityScenarioRule;
+
+import com.android.car.ui.FocusParkingView;
+import com.android.car.ui.TrulyEmptyActivity;
+import com.android.car.ui.baselayout.Insets;
+import com.android.car.ui.core.CarUi;
+import com.android.car.ui.sharedlibrarysupport.SharedLibraryFactorySingleton;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+/** A test of {@link com.android.car.ui.core.CarUi#installBaseLayoutAround} */
+@RunWith(Parameterized.class)
+public class InstallBaseLayoutAroundTest {
+
+ @Parameterized.Parameters
+ public static Object[] data() {
+ // It's important to do no shared library first, so that the shared library will
+ // still be enabled when this test finishes
+ return new Object[] { false, true };
+ }
+
+ private final boolean mSharedLibEnabled;
+
+ public InstallBaseLayoutAroundTest(boolean sharedLibEnabled) {
+ mSharedLibEnabled = sharedLibEnabled;
+ SharedLibraryFactorySingleton.setSharedLibEnabled(sharedLibEnabled);
+ }
+
+ @Rule
+ public final ActivityScenarioRule<TrulyEmptyActivity> mScenarioRule =
+ new ActivityScenarioRule<>(TrulyEmptyActivity.class);
+
+ @Test
+ public void test_installBaseLayoutAround_createsToolbar() {
+ onView(isAssignableFrom(FocusParkingView.class)).check(doesNotExist());
+
+ ToolbarController[] toolbar = new ToolbarController[] { null };
+ Insets[] insets = new Insets[] { null };
+ mScenarioRule.getScenario().onActivity(activity -> {
+ toolbar[0] = CarUi.installBaseLayoutAround(
+ activity.requireViewById(android.R.id.content),
+ i -> insets[0] = i,
+ true);
+ if (toolbar[0] != null) {
+ toolbar[0].setTitle("Hello, world!");
+ }
+ });
+
+ assertNotNull(toolbar[0]);
+ onView(withText("Hello, world!")).check(matches(isDisplayed()));
+
+ assertNotNull(insets[0]);
+ // Technically this doesn't have to be true depending on the OEM's customizations
+ assertTrue(insets[0].getTop() > 0);
+ onView(isAssignableFrom(FocusParkingView.class)).check(matches(isDisplayed()));
+ }
+
+ @Test
+ public void test_installBaseLayoutAround_doesntCreateToolbar() {
+ onView(isAssignableFrom(FocusParkingView.class)).check(doesNotExist());
+
+ ToolbarController[] toolbar = new ToolbarController[] { null };
+ mScenarioRule.getScenario().onActivity(activity ->
+ toolbar[0] = CarUi.installBaseLayoutAround(
+ activity.requireViewById(android.R.id.content),
+ i -> {},
+ false));
+
+ assertNull(toolbar[0]);
+ onView(isAssignableFrom(FocusParkingView.class)).check(matches(isDisplayed()));
+ }
+
+ @Test
+ public void test_emptyactivity_doesnthaveinsetsortoolbar() {
+ Insets[] insets = new Insets[] { new Insets() };
+ mScenarioRule.getScenario().onActivity(activity -> insets[0] = CarUi.getInsets(activity));
+ assertNull(insets[0]);
+
+ ToolbarController[] toolbar = new ToolbarController[] { new EmptyToolbarController() };
+ mScenarioRule.getScenario().onActivity(activity -> toolbar[0] = CarUi.getToolbar(activity));
+ assertNull(toolbar[0]);
+ }
+}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/toolbar/ToolbarTest.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/toolbar/ToolbarTest.java
index abd5c15..0971722 100644
--- a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/toolbar/ToolbarTest.java
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/toolbar/ToolbarTest.java
@@ -28,6 +28,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static junit.framework.Assert.assertNotNull;
import static junit.framework.TestCase.assertEquals;
import android.content.Context;
@@ -36,6 +37,7 @@
import androidx.test.ext.junit.rules.ActivityScenarioRule;
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.car.ui.baselayout.Insets;
import com.android.car.ui.core.CarUi;
import com.android.car.ui.sharedlibrarysupport.SharedLibraryFactorySingleton;
import com.android.car.ui.test.R;
@@ -244,6 +246,13 @@
}
}
+ @Test
+ public void test_requireInsets_returnsInsets() {
+ Insets[] insets = new Insets[] { null };
+ mScenarioRule.getScenario().onActivity(activity ->
+ insets[0] = CarUi.requireInsets(activity));
+ assertNotNull(insets[0]);
+ }
private void runWithToolbar(Consumer<ToolbarController> toRun) {
mScenarioRule.getScenario().onActivity(activity -> {
diff --git a/car-ui-lib/referencedesign/sharedlibrary/src/main/java/com/chassis/car/ui/sharedlibrary/toolbar/BaseLayoutInstaller.java b/car-ui-lib/referencedesign/sharedlibrary/src/main/java/com/chassis/car/ui/sharedlibrary/toolbar/BaseLayoutInstaller.java
index 9a7c13c..602777a 100644
--- a/car-ui-lib/referencedesign/sharedlibrary/src/main/java/com/chassis/car/ui/sharedlibrary/toolbar/BaseLayoutInstaller.java
+++ b/car-ui-lib/referencedesign/sharedlibrary/src/main/java/com/chassis/car/ui/sharedlibrary/toolbar/BaseLayoutInstaller.java
@@ -23,6 +23,7 @@
import android.widget.FrameLayout;
import android.widget.LinearLayout;
+import androidx.annotation.LayoutRes;
import androidx.annotation.Nullable;
import com.android.car.ui.sharedlibrary.oemapis.FocusAreaOEMV1;
@@ -54,11 +55,6 @@
@Nullable Function<Context, FocusParkingViewOEMV1> focusParkingViewFactory,
@Nullable Function<Context, FocusAreaOEMV1> focusAreaFactory) {
- if (!toolbarEnabled) {
- // We don't need a toolbar-less base layout in this design, so we're done.
- return null;
- }
-
Context activityContext = contentView.getContext();
// Add the configuration from the activity context to the shared library context,
@@ -67,8 +63,11 @@
sharedLibraryContext = sharedLibraryContext.createConfigurationContext(
activityContext.getResources().getConfiguration());
+ @LayoutRes int layout = toolbarEnabled
+ ? R.layout.base_layout_toolbar
+ : R.layout.base_layout;
FrameLayout baseLayout = (FrameLayout) LayoutInflater.from(sharedLibraryContext).inflate(
- R.layout.base_layout_toolbar, null, false);
+ layout, null, false);
// Replace the app's content view with a base layout
ViewGroup contentViewParent = (ViewGroup) contentView.getParent();
@@ -103,7 +102,7 @@
// the FocusArea using the app's context, so that it can access it's resources,
// but we want children of the FocusArea to use the shared library context, so we can
// access shared library resources.
- if (focusAreaFactory != null) {
+ if (focusAreaFactory != null && toolbarEnabled) {
LinearLayout focusArea = focusAreaFactory.apply(activityContext).getView();
if (focusArea != null) {
View toolbar = baseLayout.requireViewById(R.id.toolbar_background);
@@ -116,8 +115,11 @@
}
- ToolbarControllerOEMV1 toolbarController = new ToolbarControllerImpl(
- baseLayout, sharedLibraryContext, activityContext);
+ ToolbarControllerOEMV1 toolbarController = null;
+ if (toolbarEnabled) {
+ toolbarController = new ToolbarControllerImpl(
+ baseLayout, sharedLibraryContext, activityContext);
+ }
InsetsUpdater updater = new InsetsUpdater(baseLayout, contentView);
updater.replaceInsetsChangedListenerWith(insetsChangedListener);
diff --git a/car-ui-lib/referencedesign/sharedlibrary/src/main/res/layout/base_layout.xml b/car-ui-lib/referencedesign/sharedlibrary/src/main/res/layout/base_layout.xml
new file mode 100644
index 0000000..fc2b830
--- /dev/null
+++ b/car-ui-lib/referencedesign/sharedlibrary/src/main/res/layout/base_layout.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 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.
+ -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <FrameLayout
+ android:id="@+id/base_layout_content_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+</FrameLayout>