Merge "Pass extras to playFromMediaId" into pi-car-dev
diff --git a/car-apps-common/src/com/android/car/apps/common/imaging/ImageViewBinder.java b/car-apps-common/src/com/android/car/apps/common/imaging/ImageViewBinder.java
index f346de0..9b13438 100644
--- a/car-apps-common/src/com/android/car/apps/common/imaging/ImageViewBinder.java
+++ b/car-apps-common/src/com/android/car/apps/common/imaging/ImageViewBinder.java
@@ -21,7 +21,6 @@
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.Size;
-import android.view.View;
import android.widget.ImageView;
import com.android.car.apps.common.CommonFlags;
@@ -57,7 +56,6 @@
protected void setDrawable(@Nullable Drawable drawable) {
if (mImageView != null) {
mImageView.setImageDrawable(drawable);
- mImageView.setVisibility((drawable != null) ? View.VISIBLE : View.GONE);
if (mFlagBitmaps) {
CommonFlags flags = CommonFlags.getInstance(mImageView.getContext());
if (flags.shouldFlagImproperImageRefs()) {
diff --git a/car-media-common/src/com/android/car/media/common/MetadataController.java b/car-media-common/src/com/android/car/media/common/MetadataController.java
index 341c129..49e5a26 100644
--- a/car-media-common/src/com/android/car/media/common/MetadataController.java
+++ b/car-media-common/src/com/android/car/media/common/MetadataController.java
@@ -120,6 +120,8 @@
ViewUtils.setVisible(artist, !TextUtils.isEmpty(artistName));
}
+ ViewUtils.setVisible(albumArt, true);
+
mAlbumArtBinder.setImage(context, metadata.getArtworkKey());
});
diff --git a/car-ui-lib/generate_rros.mk b/car-ui-lib/generate_rros.mk
index 4e7931a..7e93c36 100644
--- a/car-ui-lib/generate_rros.mk
+++ b/car-ui-lib/generate_rros.mk
@@ -14,7 +14,7 @@
# limitations under the License.
#
-# Generates one RRO for a given package
+# Generates one RRO for a given package.
# $(1) target package name
# $(2) name of the RRO set (e.g. "base")
# $(3) resources folder
@@ -23,8 +23,8 @@
rro_package_name := $(2)-$(subst .,-,$(1))
LOCAL_RESOURCE_DIR := $(3)
+ LOCAL_RRO_THEME := $$(rro_package_name)
LOCAL_PACKAGE_NAME := $$(rro_package_name)
- LOCAL_PRODUCT_MODULE := true
LOCAL_CERTIFICATE := platform
LOCAL_SDK_VERSION := current
diff --git a/car-ui-lib/src/com/android/car/ui/pagedrecyclerview/DefaultScrollBar.java b/car-ui-lib/src/com/android/car/ui/pagedrecyclerview/DefaultScrollBar.java
index c98d114..3dbb6aa 100644
--- a/car-ui-lib/src/com/android/car/ui/pagedrecyclerview/DefaultScrollBar.java
+++ b/car-ui-lib/src/com/android/car/ui/pagedrecyclerview/DefaultScrollBar.java
@@ -29,6 +29,7 @@
import android.widget.ImageView;
import androidx.annotation.IntRange;
+import androidx.annotation.VisibleForTesting;
import androidx.recyclerview.widget.OrientationHelper;
import androidx.recyclerview.widget.RecyclerView;
@@ -43,16 +44,19 @@
* been ported from the PLV with minor updates.
*/
class DefaultScrollBar implements ScrollBar {
+
+ @VisibleForTesting
+ int mPaddingStart;
+ @VisibleForTesting
+ int mPaddingEnd;
+
private float mButtonDisabledAlpha;
- private static final String TAG = "DefaultScrollBar";
private PagedSnapHelper mSnapHelper;
private ImageView mUpButton;
private View mScrollView;
private View mScrollThumb;
private ImageView mDownButton;
- private int mPaddingStart;
- private int mPaddingEnd;
private int mSeparatingMargin;
@@ -75,7 +79,7 @@
@ScrollBarPosition int scrollBarPosition,
boolean scrollBarAboveRecyclerView) {
- this.mRecyclerView = rv;
+ mRecyclerView = rv;
LayoutInflater inflater =
(LayoutInflater) rv.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
@@ -84,7 +88,7 @@
mScrollView = inflater.inflate(R.layout.car_ui_pagedrecyclerview_scrollbar, parent, false);
mScrollView.setLayoutParams(
- new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));
+ new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));
Resources res = rv.getContext().getResources();
diff --git a/car-ui-lib/src/com/android/car/ui/pagedrecyclerview/PagedSmoothScroller.java b/car-ui-lib/src/com/android/car/ui/pagedrecyclerview/PagedSmoothScroller.java
index 1b73b7a..7fb0de9 100644
--- a/car-ui-lib/src/com/android/car/ui/pagedrecyclerview/PagedSmoothScroller.java
+++ b/car-ui-lib/src/com/android/car/ui/pagedrecyclerview/PagedSmoothScroller.java
@@ -25,6 +25,7 @@
import com.android.car.ui.R;
import com.android.car.ui.utils.ResourceUtils;
+import com.android.internal.annotations.VisibleForTesting;
/**
* Code drop from {androidx.car.widget.PagedSmoothScroller}
@@ -37,12 +38,16 @@
* </ul>
*/
public class PagedSmoothScroller extends LinearSmoothScroller {
- private float mMillisecondsPerInch;
- private float mDecelerationTimeDivisor;
- private float mMillisecondsPerPixel;
-
- private Interpolator mInterpolator;
- private int mDensityDpi;
+ @VisibleForTesting
+ float mMillisecondsPerInch;
+ @VisibleForTesting
+ float mDecelerationTimeDivisor;
+ @VisibleForTesting
+ float mMillisecondsPerPixel;
+ @VisibleForTesting
+ Interpolator mInterpolator;
+ @VisibleForTesting
+ int mDensityDpi;
public PagedSmoothScroller(Context context) {
super(context);
diff --git a/car-ui-lib/src/com/android/car/ui/toolbar/Toolbar.java b/car-ui-lib/src/com/android/car/ui/toolbar/Toolbar.java
index e656aa0..ba92c40 100644
--- a/car-ui-lib/src/com/android/car/ui/toolbar/Toolbar.java
+++ b/car-ui-lib/src/com/android/car/ui/toolbar/Toolbar.java
@@ -23,11 +23,13 @@
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -60,6 +62,7 @@
public interface OnHeightChangedListener {
/**
* Will be called when the height of the toolbar is changed.
+ *
* @param height new height of the toolbar
*/
void onHeightChanged(int height);
@@ -158,8 +161,6 @@
};
private AlertDialog mOverflowDialog;
-
-
public Toolbar(Context context) {
this(context, null);
}
@@ -262,7 +263,15 @@
}
});
- handleToolbarHeightChangeListeners(getHeight());
+ getViewTreeObserver().addOnGlobalLayoutListener(
+ new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ for (OnHeightChangedListener listener : mOnHeightChangedListeners) {
+ listener.onHeightChanged(getHeight());
+ }
+ }
+ });
}
@Override
@@ -309,35 +318,47 @@
SavedState(Parcel in) {
super(in);
- mTitle = in.readCharSequence();
+ mTitle = readCharSequence(in);
mNavButtonMode = NavButtonMode.valueOf(in.readString());
- mSearchHint = in.readCharSequence();
- mBackgroundShown = in.readBoolean();
- mShowMenuItemsWhileSearching = in.readBoolean();
+ mSearchHint = readCharSequence(in);
+ mBackgroundShown = in.readInt() != 0;
+ mShowMenuItemsWhileSearching = in.readInt() != 0;
mState = State.valueOf(in.readString());
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
- out.writeCharSequence(mTitle);
+ writeCharSequence(out, mTitle);
out.writeString(mNavButtonMode.name());
- out.writeCharSequence(mSearchHint);
- out.writeBoolean(mBackgroundShown);
- out.writeBoolean(mShowMenuItemsWhileSearching);
+ writeCharSequence(out, mSearchHint);
+ out.writeInt(mBackgroundShown ? 1 : 0);
+ out.writeInt(mShowMenuItemsWhileSearching ? 1 : 0);
out.writeString(mState.name());
}
public static final Parcelable.Creator<SavedState> CREATOR =
new Parcelable.Creator<SavedState>() {
+ @Override
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
+ @Override
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
+
+ /** Replacement of hidden Parcel#readCharSequence(Parcel) */
+ private static CharSequence readCharSequence(Parcel in) {
+ return TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ }
+
+ /** Replacement of hidden Parcel#writeCharSequence(Parcel, CharSequence) */
+ private static void writeCharSequence(Parcel dest, CharSequence val) {
+ TextUtils.writeToParcel(val, dest, 0);
+ }
}
/**
@@ -642,8 +663,8 @@
mNavIconContainer.setOnClickListener(state != State.HOME ? backClickListener : null);
mNavIconContainer.setClickable(state != State.HOME);
boolean hasTabs = mTabLayout.getTabCount() > 0;
- boolean showTitle = state == State.SUBPAGE || state == State.HOME
- && (!mTitleAndTabsAreMutuallyExclusive || !hasTabs);
+ boolean showTitle = state == State.SUBPAGE
+ || (state == State.HOME && (!mTitleAndTabsAreMutuallyExclusive || !hasTabs));
mTitle.setVisibility(showTitle ? VISIBLE : GONE);
mTabLayout.setVisibility(state == State.HOME && hasTabs ? VISIBLE : GONE);
mSearchView.setVisibility(state == State.SEARCH ? VISIBLE : GONE);
diff --git a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/toolbar/ToolbarActivity.java b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/toolbar/ToolbarActivity.java
index 531c3a8..e2d3346 100644
--- a/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/toolbar/ToolbarActivity.java
+++ b/car-ui-lib/tests/paintbooth/src/com/android/car/ui/paintbooth/toolbar/ToolbarActivity.java
@@ -19,6 +19,7 @@
import android.app.AlertDialog;
import android.os.Bundle;
import android.text.InputType;
+import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -27,7 +28,6 @@
import android.widget.Toast;
import androidx.annotation.NonNull;
-import androidx.core.util.Pair;
import com.android.car.ui.pagedrecyclerview.PagedRecyclerView;
import com.android.car.ui.paintbooth.R;
@@ -91,7 +91,7 @@
new AlertDialog.Builder(this)
.setView(textBox)
.setTitle("Enter the index of the MenuItem to toggle")
- .setPositiveButton("Ok", ((dialog, which) -> {
+ .setPositiveButton("Ok", (dialog, which) -> {
try {
MenuItem item = mMenuItems.get(
Integer.parseInt(textBox.getText().toString()));
@@ -102,7 +102,7 @@
+ "\", valid range is 0 to " + (mMenuItems.size() - 1),
Toast.LENGTH_LONG).show();
}
- }))
+ })
.show();
}));
@@ -161,7 +161,7 @@
}
private PagedRecyclerView.Adapter mAdapter = new PagedRecyclerView.Adapter() {
-
+ @Override
public int getItemCount() {
return mButtons.size();
}
diff --git a/car-ui-lib/tests/robotests/Android.mk b/car-ui-lib/tests/robotests/Android.mk
new file mode 100644
index 0000000..053e733
--- /dev/null
+++ b/car-ui-lib/tests/robotests/Android.mk
@@ -0,0 +1,75 @@
+LOCAL_PATH := $(call my-dir)
+
+############################################################
+# CarUi lib just for Robolectric test target. #
+############################################################
+include $(CLEAR_VARS)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_PACKAGE_NAME := CarUi
+LOCAL_PRIVATE_PLATFORM_APIS := true
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_USE_AAPT2 := true
+
+LOCAL_PRIVILEGED_MODULE := true
+
+LOCAL_JAVA_LIBRARIES := android.car
+
+LOCAL_STATIC_ANDROID_LIBRARIES := \
+ car-ui-lib
+
+include $(BUILD_PACKAGE)
+
+################################################
+# Car Ui Robolectric test target. #
+################################################
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := CarUiRoboTests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAVA_RESOURCE_DIRS := config
+
+# Include the testing libraries
+LOCAL_JAVA_LIBRARIES := \
+ android.car \
+ robolectric_android-all-stub \
+ Robolectric_all-target \
+ mockito-robolectric-prebuilt \
+ testng \
+ truth-prebuilt
+
+
+LOCAL_INSTRUMENTATION_FOR := CarUi
+
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+##################################################################
+# Car Ui runner target to run the previous target. #
+##################################################################
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := RunCarUiRoboTests
+
+LOCAL_JAVA_LIBRARIES := \
+ android.car \
+ CarUiRoboTests \
+ robolectric_android-all-stub \
+ Robolectric_all-target \
+ mockito-robolectric-prebuilt \
+ testng \
+ truth-prebuilt
+
+LOCAL_TEST_PACKAGE := CarUi
+
+LOCAL_ROBOTEST_FILES := $(filter-out %/BaseRobolectricTest.java,\
+ $(call find-files-in-subdirs,$(LOCAL_PATH)/src,*Test.java,.))
+
+LOCAL_INSTRUMENT_SOURCE_DIRS := $(dir $(LOCAL_PATH))../src
+
+include external/robolectric-shadows/run_robotests.mk
diff --git a/car-ui-lib/tests/robotests/AndroidManifest.xml b/car-ui-lib/tests/robotests/AndroidManifest.xml
new file mode 100644
index 0000000..64926b8
--- /dev/null
+++ b/car-ui-lib/tests/robotests/AndroidManifest.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 Google Inc.
+
+ 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"
+ package="com.android.car.ui.robotests">
+</manifest>
diff --git a/car-ui-lib/tests/robotests/config/robolectric.properties b/car-ui-lib/tests/robotests/config/robolectric.properties
new file mode 100644
index 0000000..8768f6b
--- /dev/null
+++ b/car-ui-lib/tests/robotests/config/robolectric.properties
@@ -0,0 +1,17 @@
+#
+# Copyright (C) 2019 Google Inc.
+#
+# 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=packages/apps/Car/libs/car-ui-lib/tests/robotests/AndroidManifest.xml
+sdk=NEWEST_SDK
diff --git a/car-ui-lib/tests/robotests/src/CarUiRobolectricTestRunner.java b/car-ui-lib/tests/robotests/src/CarUiRobolectricTestRunner.java
new file mode 100644
index 0000000..7070a88
--- /dev/null
+++ b/car-ui-lib/tests/robotests/src/CarUiRobolectricTestRunner.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 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.car.ui;
+
+import androidx.annotation.NonNull;
+
+import org.junit.runners.model.InitializationError;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.manifest.AndroidManifest;
+import org.robolectric.res.Fs;
+import org.robolectric.res.ResourcePath;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Custom test runner for CarUi. This is needed because the default behavior for
+ * robolectric is just to grab the resource directory in the target package.
+ * We want to override this to add several spanning different projects.
+ */
+public class CarUiRobolectricTestRunner extends RobolectricTestRunner {
+ private static final Map<String, String> AAR_VERSIONS;
+ private static final String SUPPORT_RESOURCE_PATH_TEMPLATE =
+ "jar:file:prebuilts/sdk/current/androidx/m2repository/androidx/"
+ + "%1$s/%1$s/%2$s/%1$s-%2$s.aar!/res";
+ // contraint-layout aar lives in separate path.
+ // Note its path contains a hyphen.
+ private static final String CONSTRAINT_LAYOUT_RESOURCE_PATH_TEMPLATE =
+ "jar:file:prebuilts/sdk/current/extras/constraint-layout-x/"
+ + "%1$s/%2$s/%1$s-%2$s.aar!/res";
+
+ static {
+ AAR_VERSIONS = new HashMap<>();
+ AAR_VERSIONS.put("appcompat", "1.1.0-alpha01");
+ AAR_VERSIONS.put("constraintlayout", "1.1.2");
+ AAR_VERSIONS.put("preference", "1.1.0-alpha02");
+ }
+
+ public CarUiRobolectricTestRunner(Class<?> testClass) throws InitializationError {
+ super(testClass);
+ }
+
+ private static ResourcePath createResourcePath(@NonNull String filePath) {
+ try {
+ return new ResourcePath(null, Fs.fromURL(new URL(filePath)), null);
+ } catch (MalformedURLException e) {
+ throw new RuntimeException("CarUiRobolectricTestRunner failure", e);
+ }
+ }
+
+ /**
+ * Create the resource path for a support library component's JAR.
+ */
+ private static String createSupportResourcePathFromJar(@NonNull String componentId) {
+ if (!AAR_VERSIONS.containsKey(componentId)) {
+ throw new IllegalArgumentException("Unknown component " + componentId
+ + ". Update test with appropriate component name and version.");
+ }
+ if (componentId.equals("constraintlayout")) {
+ return String.format(CONSTRAINT_LAYOUT_RESOURCE_PATH_TEMPLATE, componentId,
+ AAR_VERSIONS.get(componentId));
+ }
+ return String.format(SUPPORT_RESOURCE_PATH_TEMPLATE, componentId,
+ AAR_VERSIONS.get(componentId));
+ }
+
+ /**
+ * We modify the AndroidManifest such that we can add required resources.
+ */
+ @Override
+ protected AndroidManifest getAppManifest(Config config) {
+ try {
+ // Using the manifest file's relative path, we can figure out the application directory.
+ URL appRoot = new URL("file:packages/apps/Car/libs/car-ui-lib/");
+ URL manifestPath = new URL(appRoot, "AndroidManifest.xml");
+ URL resDir = new URL(appRoot, "tests/robotests/res");
+ URL assetsDir = new URL(appRoot, config.assetDir());
+
+ // By adding any resources from libraries we need to the AndroidManifest, we can access
+ // them from within the parallel universe's resource loader.
+ return new AndroidManifest(Fs.fromURL(manifestPath), Fs.fromURL(resDir),
+ Fs.fromURL(assetsDir)) {
+ @Override
+ public List<ResourcePath> getIncludedResourcePaths() {
+ List<ResourcePath> paths = super.getIncludedResourcePaths();
+ paths.add(createResourcePath("file:packages/apps/Car/libs/car-ui-lib/res"));
+
+ // Support library resources. These need to point to the prebuilts of support
+ // library and not the source.
+ paths.add(createResourcePath(createSupportResourcePathFromJar("appcompat")));
+ paths.add(createResourcePath(
+ createSupportResourcePathFromJar("constraintlayout")));
+ paths.add(createResourcePath(createSupportResourcePathFromJar("preference")));
+
+ return paths;
+ }
+ };
+ } catch (MalformedURLException e) {
+ throw new RuntimeException("CarUiRobolectricTestRunner failure", e);
+ }
+ }
+}
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/pagedrecyclerview/CarUxRestrictionsUtilTest.java b/car-ui-lib/tests/robotests/src/com/android/car/ui/pagedrecyclerview/CarUxRestrictionsUtilTest.java
new file mode 100644
index 0000000..b5031d1
--- /dev/null
+++ b/car-ui-lib/tests/robotests/src/com/android/car/ui/pagedrecyclerview/CarUxRestrictionsUtilTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 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.car.ui.pagedrecyclerview;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.car.drivingstate.CarUxRestrictions;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class CarUxRestrictionsUtilTest {
+ private int[] mRestrictionsArray;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mRestrictionsArray = new int[]{
+ CarUxRestrictions.UX_RESTRICTIONS_NO_DIALPAD,
+ CarUxRestrictions.UX_RESTRICTIONS_NO_KEYBOARD,
+ CarUxRestrictions.UX_RESTRICTIONS_NO_DIALPAD
+ | CarUxRestrictions.UX_RESTRICTIONS_NO_KEYBOARD,
+ CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED
+ };
+ }
+
+ @Test
+ public void testNullActiveRestriction() {
+ CarUxRestrictions activeRestrictions = null;
+ boolean[] expectedResults = {true, true, true, true};
+ for (int i = 0; i < mRestrictionsArray.length; i++) {
+ boolean actualResult = CarUxRestrictionsUtil.isRestricted(mRestrictionsArray[i],
+ activeRestrictions);
+ assertThat(actualResult == expectedResults[i]).isTrue();
+ }
+ }
+
+ @Test
+ public void testOneActiveRestriction() {
+ CarUxRestrictions activeRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */true,
+ CarUxRestrictions.UX_RESTRICTIONS_NO_DIALPAD, /* timestamp= */0).build();
+ boolean[] expectedResults = {true, false, true, true};
+ for (int i = 0; i < mRestrictionsArray.length; i++) {
+ boolean actualResult = CarUxRestrictionsUtil.isRestricted(mRestrictionsArray[i],
+ activeRestrictions);
+ assertThat(actualResult == expectedResults[i]).isTrue();
+ }
+ }
+
+ @Test
+ public void testMultipleActiveRestrictions() {
+ CarUxRestrictions activeRestrictions = new CarUxRestrictions.Builder(/* reqOpt= */true,
+ CarUxRestrictions.UX_RESTRICTIONS_NO_DIALPAD
+ | CarUxRestrictions.UX_RESTRICTIONS_NO_TEXT_MESSAGE, /* timestamp= */
+ 0).build();
+ boolean[] expectedResults = {true, false, true, true};
+ for (int i = 0; i < mRestrictionsArray.length; i++) {
+ boolean actualResult = CarUxRestrictionsUtil.isRestricted(mRestrictionsArray[i],
+ activeRestrictions);
+ assertThat(actualResult == expectedResults[i]).isTrue();
+ }
+ }
+}
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/pagedrecyclerview/DefaultScrollBarTest.java b/car-ui-lib/tests/robotests/src/com/android/car/ui/pagedrecyclerview/DefaultScrollBarTest.java
new file mode 100644
index 0000000..f0ca4a6
--- /dev/null
+++ b/car-ui-lib/tests/robotests/src/com/android/car/ui/pagedrecyclerview/DefaultScrollBarTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright 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.car.ui.pagedrecyclerview;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertThrows;
+
+import android.content.Context;
+import android.widget.FrameLayout;
+
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.car.ui.CarUiRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(CarUiRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class DefaultScrollBarTest {
+
+ private Context mContext;
+ private ScrollBar mScrollBar;
+
+ @Mock
+ private RecyclerView mRecyclerView;
+ @Mock
+ private FrameLayout mParent;
+ @Mock
+ private FrameLayout.LayoutParams mLayoutParams;
+ @Mock
+ private RecyclerView.RecycledViewPool mRecycledViewPool;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+
+ mScrollBar = new DefaultScrollBar();
+ }
+
+ @Test
+ public void initialize_shouldInitializeScrollListener() {
+ when(mRecyclerView.getContext()).thenReturn(mContext);
+ when(mRecyclerView.getParent()).thenReturn(mParent);
+ when(mRecyclerView.getRecycledViewPool()).thenReturn(mRecycledViewPool);
+ when(mParent.generateLayoutParams(any())).thenReturn(mLayoutParams);
+
+ mScrollBar.initialize(mRecyclerView, 10, PagedRecyclerView.ScrollBarPosition.START, true);
+
+ // called once in DefaultScrollBar and once in SnapHelper while setting up the call backs
+ // when we use attachToRecyclerView(recyclerview)
+ verify(mRecyclerView, times(2)).addOnScrollListener(
+ any(RecyclerView.OnScrollListener.class));
+ }
+
+ @Test
+ public void initialize_shouldSetMaxRecyclerViews() {
+ when(mRecyclerView.getContext()).thenReturn(mContext);
+ when(mRecyclerView.getParent()).thenReturn(mParent);
+ when(mRecyclerView.getRecycledViewPool()).thenReturn(mRecycledViewPool);
+ when(mParent.generateLayoutParams(any())).thenReturn(mLayoutParams);
+
+ mScrollBar.initialize(mRecyclerView, 10, PagedRecyclerView.ScrollBarPosition.START, true);
+
+ verify(mRecycledViewPool).setMaxRecycledViews(0, 12);
+ }
+
+ @Test
+ public void initialize_shouldNotHaveFlingListener() {
+ when(mRecyclerView.getContext()).thenReturn(mContext);
+ when(mRecyclerView.getParent()).thenReturn(mParent);
+ when(mRecyclerView.getRecycledViewPool()).thenReturn(mRecycledViewPool);
+ when(mParent.generateLayoutParams(any())).thenReturn(mLayoutParams);
+
+ mScrollBar.initialize(mRecyclerView, 10, PagedRecyclerView.ScrollBarPosition.START, true);
+
+ verify(mRecyclerView).setOnFlingListener(null);
+ }
+
+ @Test
+ public void setPadding_shouldSetStartAndEndPadding() {
+ when(mRecyclerView.getContext()).thenReturn(mContext);
+ when(mRecyclerView.getParent()).thenReturn(mParent);
+ when(mRecyclerView.getRecycledViewPool()).thenReturn(mRecycledViewPool);
+ when(mParent.generateLayoutParams(any())).thenReturn(mLayoutParams);
+
+ mScrollBar.initialize(mRecyclerView, 10, PagedRecyclerView.ScrollBarPosition.START, true);
+ mScrollBar.setPadding(10, 20);
+
+ DefaultScrollBar defaultScrollBar = (DefaultScrollBar) mScrollBar;
+
+ assertThat(defaultScrollBar.mPaddingStart).isEqualTo(10);
+ assertThat(defaultScrollBar.mPaddingEnd).isEqualTo(20);
+ }
+
+ @Test
+ public void setPadding_shouldThrowErrorWithoutInitialization() {
+ assertThrows(NullPointerException.class, () -> mScrollBar.setPadding(10, 20));
+ }
+
+ @Test
+ public void requestLayout_shouldThrowErrorWithoutInitialization() {
+ assertThrows(NullPointerException.class, () -> mScrollBar.requestLayout());
+ }
+}
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/pagedrecyclerview/PagedRecyclerViewAdapterTest.java b/car-ui-lib/tests/robotests/src/com/android/car/ui/pagedrecyclerview/PagedRecyclerViewAdapterTest.java
new file mode 100644
index 0000000..bd95b58
--- /dev/null
+++ b/car-ui-lib/tests/robotests/src/com/android/car/ui/pagedrecyclerview/PagedRecyclerViewAdapterTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 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.car.ui.pagedrecyclerview;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.view.ViewGroup;
+
+import com.android.car.ui.CarUiRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(CarUiRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class PagedRecyclerViewAdapterTest {
+
+ private Context mContext;
+ private PagedRecyclerViewAdapter mPagedRecyclerViewAdapter;
+
+ @Mock
+ private ViewGroup mParent;
+ @Mock
+ private ViewGroup.LayoutParams mLayoutParams;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = RuntimeEnvironment.application;
+ mPagedRecyclerViewAdapter = new PagedRecyclerViewAdapter();
+ }
+
+ @Test
+ public void getItemCount_shouldAlwaysBeOne() {
+ assertThat(mPagedRecyclerViewAdapter.getItemCount()).isEqualTo(1);
+ }
+
+ @Test
+ public void onCreateViewHolder_frameLayoutNotNull() {
+
+ when(mParent.getContext()).thenReturn(mContext);
+ when(mParent.generateLayoutParams(any())).thenReturn(mLayoutParams);
+
+ PagedRecyclerViewAdapter.NestedRowViewHolder nestedRowViewHolder =
+ mPagedRecyclerViewAdapter.onCreateViewHolder(mParent, 0);
+
+ assertThat(nestedRowViewHolder.frameLayout).isNotNull();
+ }
+}
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/pagedrecyclerview/PagedSmoothScrollerTest.java b/car-ui-lib/tests/robotests/src/com/android/car/ui/pagedrecyclerview/PagedSmoothScrollerTest.java
new file mode 100644
index 0000000..126883e
--- /dev/null
+++ b/car-ui-lib/tests/robotests/src/com/android/car/ui/pagedrecyclerview/PagedSmoothScrollerTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 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.car.ui.pagedrecyclerview;
+
+import static androidx.recyclerview.widget.LinearSmoothScroller.SNAP_TO_START;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+
+import com.android.car.ui.CarUiRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(CarUiRobolectricTestRunner.class)
+public class PagedSmoothScrollerTest {
+
+ private Context mContext;
+ private PagedSmoothScroller mPagedSmoothScroller;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mPagedSmoothScroller = new PagedSmoothScroller(mContext);
+ }
+
+ @Test
+ public void calculateTimeForScrolling_shouldInitializeAllValues() {
+ assertThat(mPagedSmoothScroller.mMillisecondsPerInch).isNotEqualTo(0);
+ assertThat(mPagedSmoothScroller.mDecelerationTimeDivisor).isNotEqualTo(0);
+ assertThat(mPagedSmoothScroller.mMillisecondsPerPixel).isNotEqualTo(0);
+ assertThat(mPagedSmoothScroller.mInterpolator).isNotNull();
+ assertThat(mPagedSmoothScroller.mDensityDpi).isNotEqualTo(0);
+ }
+
+ @Test
+ public void getVerticalSnapPreference_shouldReturnSnapToStart() {
+ assertThat(mPagedSmoothScroller.getVerticalSnapPreference()).isEqualTo(SNAP_TO_START);
+ }
+
+ @Test
+ public void calculateTimeForScrolling_shouldReturnMultiplierOfMillisecondsPerPixel() {
+ assertThat(mPagedSmoothScroller.calculateTimeForScrolling(20)).isEqualTo(
+ (int) Math.ceil(Math.abs(20) * mPagedSmoothScroller.mMillisecondsPerPixel));
+ }
+
+ @Test
+ public void calculateTimeForDeceleration_shouldReturnNotBeZero() {
+ assertThat(mPagedSmoothScroller.calculateTimeForDeceleration(20)).isNotEqualTo(0);
+ }
+}
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/pagedrecyclerview/PagedSnapHelperTest.java b/car-ui-lib/tests/robotests/src/com/android/car/ui/pagedrecyclerview/PagedSnapHelperTest.java
new file mode 100644
index 0000000..ef6c5af
--- /dev/null
+++ b/car-ui-lib/tests/robotests/src/com/android/car/ui/pagedrecyclerview/PagedSnapHelperTest.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright 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.car.ui.pagedrecyclerview;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.graphics.PointF;
+import android.view.View;
+
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.car.ui.CarUiRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(CarUiRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class PagedSnapHelperTest {
+
+ private Context mContext;
+ private PagedSnapHelper mPagedSnapHelper;
+
+ @Mock
+ private RecyclerView mRecyclerView;
+ @Mock
+ private LinearLayoutManager mLayoutManager;
+ @Mock
+ private RecyclerView.Adapter mAdapter;
+ @Mock
+ private View mChild;
+ @Mock
+ private RecyclerView.LayoutParams mLayoutParams;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+
+ mPagedSnapHelper = new PagedSnapHelper(mContext);
+
+ when(mRecyclerView.getContext()).thenReturn(mContext);
+ mPagedSnapHelper.attachToRecyclerView(mRecyclerView);
+ }
+
+ @Test
+ public void smoothScrollBy_invalidSnapPosition_shouldCallRecylerViewSmoothScrollBy() {
+ when(mRecyclerView.getLayoutManager()).thenReturn(mLayoutManager);
+
+ mPagedSnapHelper.smoothScrollBy(10);
+
+ verify(mRecyclerView).smoothScrollBy(0, 10);
+ }
+
+ @Test
+ public void smoothScrollBy_invalidSnapPositionNoItem_shouldCallRecylerViewSmoothScrollBy() {
+ when(mRecyclerView.getLayoutManager()).thenReturn(mLayoutManager);
+ when(mLayoutManager.getItemCount()).thenReturn(0);
+
+ mPagedSnapHelper.smoothScrollBy(10);
+
+ verify(mRecyclerView).smoothScrollBy(0, 10);
+ }
+
+ @Test
+ public void smoothScrollBy_invalidSnapPositionNoView_shouldCallRecylerViewSmoothScrollBy() {
+ when(mRecyclerView.getLayoutManager()).thenReturn(mLayoutManager);
+ when(mLayoutManager.getItemCount()).thenReturn(10);
+ when(mLayoutManager.canScrollVertically()).thenReturn(false);
+ when(mLayoutManager.canScrollHorizontally()).thenReturn(false);
+
+ mPagedSnapHelper.smoothScrollBy(10);
+
+ verify(mRecyclerView).smoothScrollBy(0, 10);
+ }
+
+ @Test
+ public void smoothScrollBy_invalidSnapPositionNoVectore_shouldCallRecylerViewSmoothScrollBy() {
+ when(mRecyclerView.getLayoutManager()).thenReturn(mLayoutManager);
+ when(mLayoutManager.getItemCount()).thenReturn(10);
+ when(mLayoutManager.canScrollVertically()).thenReturn(true);
+ when(mLayoutManager.getChildCount()).thenReturn(1);
+ when(mChild.getLayoutParams()).thenReturn(mLayoutParams);
+ when(mLayoutManager.getChildAt(0)).thenReturn(mChild);
+
+ mPagedSnapHelper.smoothScrollBy(10);
+
+ verify(mRecyclerView).smoothScrollBy(0, 10);
+ }
+
+ @Test
+ public void smoothScrollBy_invalidSnapPositionNoDelta_shouldCallRecylerViewSmoothScrollBy() {
+ when(mRecyclerView.getLayoutManager()).thenReturn(mLayoutManager);
+ when(mLayoutManager.getItemCount()).thenReturn(1);
+ when(mLayoutManager.canScrollVertically()).thenReturn(true);
+ when(mLayoutManager.getChildCount()).thenReturn(1);
+ // no delta
+ when(mLayoutManager.getDecoratedBottom(any())).thenReturn(0);
+ when(mChild.getLayoutParams()).thenReturn(mLayoutParams);
+ when(mLayoutManager.getChildAt(0)).thenReturn(mChild);
+
+ PointF vectorForEnd = new PointF(100, 100);
+ when(mLayoutManager.computeScrollVectorForPosition(0)).thenReturn(vectorForEnd);
+
+ mPagedSnapHelper.smoothScrollBy(10);
+
+ verify(mRecyclerView).smoothScrollBy(0, 10);
+ }
+
+ @Test
+ public void smoothScrollBy_validSnapPosition_shouldCallRecylerViewSmoothScrollBy() {
+ when(mRecyclerView.getLayoutManager()).thenReturn(mLayoutManager);
+ when(mLayoutManager.getItemCount()).thenReturn(1);
+ when(mLayoutManager.canScrollVertically()).thenReturn(true);
+ when(mLayoutManager.getChildCount()).thenReturn(1);
+ // some delta
+ when(mLayoutManager.getDecoratedBottom(any())).thenReturn(10);
+ when(mChild.getLayoutParams()).thenReturn(mLayoutParams);
+ when(mLayoutManager.getChildAt(0)).thenReturn(mChild);
+
+ PointF vectorForEnd = new PointF(100, 100);
+ when(mLayoutManager.computeScrollVectorForPosition(0)).thenReturn(vectorForEnd);
+
+ mPagedSnapHelper.smoothScrollBy(10);
+
+ verify(mLayoutManager).startSmoothScroll(any(RecyclerView.SmoothScroller.class));
+ }
+
+ @Test
+ public void calculateDistanceToFinalSnap_shouldReturnTopMarginDifference() {
+ when(mRecyclerView.getLayoutManager()).thenReturn(mLayoutManager);
+ when(mLayoutManager.getItemCount()).thenReturn(1);
+ when(mLayoutManager.canScrollVertically()).thenReturn(true);
+ when(mLayoutManager.getChildCount()).thenReturn(1);
+ // some delta
+ when(mLayoutManager.getDecoratedTop(any())).thenReturn(10);
+ when(mChild.getLayoutParams()).thenReturn(mLayoutParams);
+
+ int[] distance = mPagedSnapHelper.calculateDistanceToFinalSnap(mLayoutManager, mChild);
+
+ assertThat(distance[1]).isEqualTo(10);
+ }
+
+ @Test
+ public void calculateScrollDistance_shouldScrollHeightOfView() {
+ when(mRecyclerView.getLayoutManager()).thenReturn(mLayoutManager);
+ when(mLayoutManager.getItemCount()).thenReturn(1);
+ when(mLayoutManager.canScrollVertically()).thenReturn(true);
+ when(mLayoutManager.getChildCount()).thenReturn(1);
+ // some delta
+ when(mLayoutManager.getDecoratedTop(any())).thenReturn(10);
+ when(mChild.getLayoutParams()).thenReturn(mLayoutParams);
+ when(mLayoutManager.getChildAt(0)).thenReturn(mChild);
+ when(mLayoutManager.getHeight()).thenReturn(-50);
+
+ int[] distance = mPagedSnapHelper.calculateScrollDistance(0, 10);
+
+ assertThat(distance[1]).isEqualTo(50);
+ }
+}
diff --git a/car-ui-lib/tests/robotests/src/com/android/car/ui/pagedrecyclerview/TestConfig.java b/car-ui-lib/tests/robotests/src/com/android/car/ui/pagedrecyclerview/TestConfig.java
new file mode 100644
index 0000000..6d93746
--- /dev/null
+++ b/car-ui-lib/tests/robotests/src/com/android/car/ui/pagedrecyclerview/TestConfig.java
@@ -0,0 +1,23 @@
+/*
+ * 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.car.ui.pagedrecyclerview;
+
+public class TestConfig {
+ public static final int SDK_VERSION = 28;
+ public static final String MANIFEST_PATH =
+ "packages/apps/Car/car-ui-lib/AndroidManifest.xml";
+}