Merge "DO NOT MERGE: Add warning not to use the shared library yet" into sc-dev
diff --git a/car-assist-lib/src/com/android/car/assist/CarVoiceInteractionSession.java b/car-assist-lib/src/com/android/car/assist/CarVoiceInteractionSession.java
index b66f5eb..8e5fef2 100644
--- a/car-assist-lib/src/com/android/car/assist/CarVoiceInteractionSession.java
+++ b/car-assist-lib/src/com/android/car/assist/CarVoiceInteractionSession.java
@@ -23,6 +23,7 @@
import android.service.voice.VoiceInteractionSession;
import androidx.annotation.StringDef;
+import androidx.core.app.NotificationManagerCompat;
import com.android.car.assist.payloadhandlers.NotificationPayloadHandler;
import com.android.car.messenger.common.Conversation;
@@ -43,18 +44,25 @@
public static final String KEY_EXCEPTION = "KEY_EXCEPTION";
/**
- * The key used for the {@link CarVoiceInteractionSession#VOICE_ACTION_HANDLE_EXCEPTION}
- * payload
+ * The key used for the {@link CarVoiceInteractionSession#VOICE_ACTION_HANDLE_EXCEPTION} payload
* {@link Bundle}. Must map to a boolean. If value is true, the Fallback Assistant that can
- * handle
- * the user's request has been disabled.
+ * handle the user's request has been disabled.
*/
public static final String KEY_FALLBACK_ASSISTANT_ENABLED = "KEY_FALLBACK_ASSISTANT_ENABLED";
/**
+ * The key used for a substitute package name the Digital Assistant should read out in lieu of
+ * package name associated with the {@link StatusBarNotification}.
+ *
+ * <p>Only system packages which lump together a bunch of unrelated stuff may substitute a
+ * different name to make the purpose of the notification more clear. The correct package label
+ * should always be accessible via SystemUI.
+ */
+ public static final String EXTRA_SUBSTITUTE_APP_NAME = "android.substName";
+
+ /**
* The key used for the payload {@link Bundle}, if a {@link StatusBarNotification} is used as
- * the
- * payload.
+ * the payload.
*/
public static final String KEY_NOTIFICATION = "KEY_NOTIFICATION";
@@ -68,39 +76,36 @@
public static final String VOICE_ACTION_NO_ACTION = "VOICE_ACTION_NO_ACTION";
/**
- * Indicates to assistant that a read action is being requested for a given payload.
- * A {@link StatusBarNotification} object will be provided in the payload
+ * Indicates to assistant that a read action is being requested for a given payload. A {@link
+ * StatusBarNotification} object will be provided in the payload
*/
public static final String VOICE_ACTION_READ_NOTIFICATION = "VOICE_ACTION_READ_NOTIFICATION";
/**
- * Indicates to assistant that a reply action is being requested for a given payload.
- * A {@link StatusBarNotification} object will be provided in the payload
+ * Indicates to assistant that a reply action is being requested for a given payload. A {@link
+ * StatusBarNotification} object will be provided in the payload
*/
public static final String VOICE_ACTION_REPLY_NOTIFICATION = "VOICE_ACTION_REPLY_NOTIFICATION";
/**
- * Indicates to assistant that a read conversation action is being requested.
- * A {@link Conversation} object will be provided in the payload.
+ * Indicates to assistant that a read conversation action is being requested. A {@link
+ * Conversation} object will be provided in the payload.
*/
public static final String VOICE_ACTION_READ_CONVERSATION = "VOICE_ACTION_READ_CONVERSATION";
/**
- * Indicates to assistant that a reply conversation action is being requested.
- * A {@link Conversation} object will be provided in the payload.
+ * Indicates to assistant that a reply conversation action is being requested. A {@link
+ * Conversation} object will be provided in the payload.
*/
public static final String VOICE_ACTION_REPLY_CONVERSATION = "VOICE_ACTION_REPLY_CONVERSATION";
/**
* Indicates to digital assistant that it should capture a SMS message from the user,
- * potentially
- * finding which contact to send the message to and which device to send the message from
- * (only if the application does not send the digital assistant this information in the
- * bundle).
- * Once the digital assistant has gathered the information from the user, it should send back
- * the PendingIntent (provided in the bundle) with the information so the application can
- * actually
- * send the SMS.
+ * potentially finding which contact to send the message to and which device to send the message
+ * from (only if the application does not send the digital assistant this information in the
+ * bundle). Once the digital assistant has gathered the information from the user, it should
+ * send back the PendingIntent (provided in the bundle) with the information so the application
+ * can actually send the SMS.
*/
public static final String VOICE_ACTION_SEND_SMS = "VOICE_ACTION_SEND_SMS";
@@ -112,8 +117,8 @@
/**
* Recipient's name. If this and the recipient phone number are not provided by the application,
- * digital assistant must do contact disambiguation but is not required to add the name
- * to the PendingIntent.
+ * digital assistant must do contact disambiguation but is not required to add the name to the
+ * PendingIntent.
*/
public static final String KEY_RECIPIENT_NAME = "KEY RECIPIENT NAME";
@@ -151,8 +156,7 @@
/** The list of exceptions the active voice service must handle. */
@StringDef({EXCEPTION_NOTIFICATION_LISTENER_PERMISSIONS_MISSING})
- public @interface ExceptionValue {
- }
+ public @interface ExceptionValue {}
/**
* Indicates to assistant that it is missing the Notification Listener permission, and should
@@ -184,7 +188,8 @@
@Override
public final void onShow(Bundle args, int showFlags) {
super.onShow(args, showFlags);
- if (args != null && isCarNotificationSource(showFlags)) {
+ addNotificationAccessExceptionIfNeeded(args);
+ if (args != null) {
String action = getRequestedVoiceAction(args);
if (!VOICE_ACTION_NO_ACTION.equals(action)) {
onShow(action, args, showFlags);
@@ -197,25 +202,53 @@
/**
* Called when the session UI is going to be shown. This is called after {@link
* #onCreateContentView} (if the session's content UI needed to be created) and immediately
- * prior
- * to the window being shown. This may be called while the window is already shown, if a show
- * request has come in while it is shown, to allow you to update the UI to match the new show
- * arguments.
+ * prior to the window being shown. This may be called while the window is already shown, if a
+ * show request has come in while it is shown, to allow you to update the UI to match the new
+ * show arguments.
*
* @param action The action that is being requested for this session (e.g. {@link
- * CarVoiceInteractionSession#VOICE_ACTION_READ_NOTIFICATION}, {@link
- * CarVoiceInteractionSession#VOICE_ACTION_REPLY_NOTIFICATION}).
- * @param args The arguments that were supplied to {@link VoiceInteractionService#showSession
- * VoiceInteractionService.showSession}.
- * @param flags The show flags originally provided to
- * {@link VoiceInteractionService#showSession
- * VoiceInteractionService.showSession}.
+ * CarVoiceInteractionSession#VOICE_ACTION_READ_NOTIFICATION}, {@link
+ * CarVoiceInteractionSession#VOICE_ACTION_REPLY_NOTIFICATION}).
+ * @param args The arguments that were supplied to {@link VoiceInteractionService#showSession
+ * VoiceInteractionService.showSession}.
+ * @param flags The show flags originally provided to {@link VoiceInteractionService#showSession
+ * VoiceInteractionService.showSession}.
*/
protected abstract void onShow(String action, Bundle args, int flags);
- /** Returns true if the request was initiated for a car notification. */
- private static boolean isCarNotificationSource(int flags) {
- return (flags & SHOW_SOURCE_NOTIFICATION) != 0;
+ /**
+ * Transforms bundle to {@link KEY_EXCEPTION} with
+ * value {@link EXCEPTION_NOTIFICATION_LISTENER_PERMISSIONS_MISSING} if
+ * Notification Listener permissions are missing.
+ */
+ private void addNotificationAccessExceptionIfNeeded(Bundle args) {
+ if (needsNotificationAccess(args)) {
+ args.putString(KEY_ACTION, VOICE_ACTION_HANDLE_EXCEPTION);
+ args.putString(KEY_EXCEPTION, EXCEPTION_NOTIFICATION_LISTENER_PERMISSIONS_MISSING);
+ args.putBoolean(KEY_FALLBACK_ASSISTANT_ENABLED, false);
+ }
+ }
+
+ private boolean needsNotificationAccess(Bundle args) {
+ return isNotificationAction(args) && !hasNotificationAccess(getContext());
+ }
+
+ /**
+ * Returns {@code true} if the given {@code args} is a notification action, {@code false}
+ * otherwise
+ */
+ private static boolean isNotificationAction(Bundle args) {
+ if (args == null) {
+ return false;
+ }
+ String action = args.getString(KEY_ACTION);
+ return VOICE_ACTION_REPLY_NOTIFICATION.equals(action)
+ || VOICE_ACTION_READ_NOTIFICATION.equals(action);
+ }
+
+ private boolean hasNotificationAccess(Context context) {
+ return NotificationManagerCompat
+ .getEnabledListenerPackages(context).contains(context.getPackageName());
}
/**
diff --git a/car-telephony-common/src/com/android/car/telephony/common/Contact.java b/car-telephony-common/src/com/android/car/telephony/common/Contact.java
index 498e92b..f40a566 100644
--- a/car-telephony-common/src/com/android/car/telephony/common/Contact.java
+++ b/car-telephony-common/src/com/android/car/telephony/common/Contact.java
@@ -32,6 +32,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Locale;
/**
* Encapsulates data about a phone Contact entry. Typically loaded from the local Contact store.
@@ -200,11 +201,21 @@
/**
* All postal addresses of this contact mapping to the unique primary key for the raw data
- * entry
+ * entry.
*/
private final List<PostalAddress> mPostalAddresses = new ArrayList<>();
/**
+ * Collator instance for proper comparison based on localized names.
+ */
+ private Collator mCollator;
+
+ /**
+ * Locale used for mCollator creation.
+ */
+ private Locale mLocale;
+
+ /**
* Parses a contact entry for a Cursor loaded from the Contact Database. A new contact will be
* created and returned.
*/
@@ -628,7 +639,7 @@
for (int i = 0; i < phoneNumberListLength; i++) {
PhoneNumber phoneNumber = source.readParcelable(PhoneNumber.class.getClassLoader());
contact.mPhoneNumbers.add(phoneNumber);
- if (phoneNumber.isPrimary()) {
+ if (phoneNumber != null && phoneNumber.isPrimary()) {
contact.mPrimaryPhoneNumber = phoneNumber;
}
}
@@ -676,8 +687,12 @@
if (type != otherType) {
return Integer.compare(type, otherType);
}
- Collator collator = Collator.getInstance();
- return collator.compare(name == null ? "" : name, otherName == null ? "" : otherName);
+ Locale currentLocale = Locale.getDefault();
+ if (mCollator == null || mLocale == null || !mLocale.equals(currentLocale)) {
+ mCollator = Collator.getInstance(currentLocale);
+ mLocale = currentLocale;
+ }
+ return mCollator.compare(name == null ? "" : name, otherName == null ? "" : otherName);
}
/**
diff --git a/car-telephony-common/tests/robotests/src/com/android/car/telephony/common/ContactTest.java b/car-telephony-common/tests/robotests/src/com/android/car/telephony/common/ContactTest.java
index 572dc8a..4825895 100644
--- a/car-telephony-common/tests/robotests/src/com/android/car/telephony/common/ContactTest.java
+++ b/car-telephony-common/tests/robotests/src/com/android/car/telephony/common/ContactTest.java
@@ -38,12 +38,18 @@
import java.util.Collections;
import java.util.List;
-
@RunWith(RobolectricTestRunner.class)
public class ContactTest {
private static final int DISPLAY_NAME_COLUMN = 1;
+ private static final int MIMETYPE_COLUMN = 2;
+ private static final int LOOK_UP_KEY_COLUMN = 3;
+ private static final int PRIMARY_KEY_COLUMN = 4;
+ private static final String PHONEBOOK_LABEL = "phonebook_label";
+ private static final int PHONEBOOK_LABEL_COLUMN = 5;
+ private static final String EMPTY_MIME = "";
+ private static final String DEFAULT_LOOK_UP_KEY = "PRIMARY";
private static final String NULL_NAME = null;
private static final String EMPTY_NAME = "";
private static final String LETTER_NAME_1 = "test";
@@ -79,94 +85,124 @@
when(mMockCursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)).thenReturn(
DISPLAY_NAME_COLUMN);
+ when(mMockCursor.getColumnIndex(ContactsContract.RawContacts.SORT_KEY_PRIMARY)).thenReturn(
+ PRIMARY_KEY_COLUMN);
+ when(mMockCursor.getColumnIndex(ContactsContract.Data.MIMETYPE)).thenReturn(
+ MIMETYPE_COLUMN);
+ when(mMockCursor.getString(MIMETYPE_COLUMN)).thenReturn(EMPTY_MIME);
+ when(mMockCursor.getColumnIndex(ContactsContract.Data.LOOKUP_KEY)).thenReturn(
+ LOOK_UP_KEY_COLUMN);
+ when(mMockCursor.getString(LOOK_UP_KEY_COLUMN)).thenReturn(DEFAULT_LOOK_UP_KEY);
+ when(mMockCursor.getColumnIndex(PHONEBOOK_LABEL)).thenReturn(
+ PHONEBOOK_LABEL_COLUMN);
+
when(mMockContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(
mMockTelephonyManager);
when(mMockTelephonyManager.getSimCountryIso()).thenReturn("");
- when(mMockCursor.getString(DISPLAY_NAME_COLUMN)).thenReturn(NULL_NAME);
+ when(mMockCursor.getString(PHONEBOOK_LABEL_COLUMN)).thenReturn("");
+ when(mMockCursor.getString(PRIMARY_KEY_COLUMN)).thenReturn(NULL_NAME);
mNullName = Contact.fromCursor(mMockContext, mMockCursor);
- when(mMockCursor.getString(DISPLAY_NAME_COLUMN)).thenReturn(EMPTY_NAME);
+ when(mMockCursor.getString(PRIMARY_KEY_COLUMN)).thenReturn(EMPTY_NAME);
mEmptyName = Contact.fromCursor(mMockContext, mMockCursor);
- when(mMockCursor.getString(DISPLAY_NAME_COLUMN)).thenReturn(LETTER_NAME_1);
+
+ when(mMockCursor.getString(PHONEBOOK_LABEL_COLUMN)).thenReturn("T");
+ when(mMockCursor.getString(PRIMARY_KEY_COLUMN)).thenReturn(LETTER_NAME_1);
mLetterName1 = Contact.fromCursor(mMockContext, mMockCursor);
- when(mMockCursor.getString(DISPLAY_NAME_COLUMN)).thenReturn(LETTER_NAME_2);
+ when(mMockCursor.getString(PRIMARY_KEY_COLUMN)).thenReturn(LETTER_NAME_2);
mLetterName2 = Contact.fromCursor(mMockContext, mMockCursor);
- when(mMockCursor.getString(DISPLAY_NAME_COLUMN)).thenReturn(DIGIT_NAME_1);
+
+ when(mMockCursor.getString(PHONEBOOK_LABEL_COLUMN)).thenReturn("#");
+ when(mMockCursor.getString(PRIMARY_KEY_COLUMN)).thenReturn(DIGIT_NAME_1);
mDigitName1 = Contact.fromCursor(mMockContext, mMockCursor);
- when(mMockCursor.getString(DISPLAY_NAME_COLUMN)).thenReturn(DIGIT_NAME_2);
+ when(mMockCursor.getString(PRIMARY_KEY_COLUMN)).thenReturn(DIGIT_NAME_2);
mDigitName2 = Contact.fromCursor(mMockContext, mMockCursor);
- when(mMockCursor.getString(DISPLAY_NAME_COLUMN)).thenReturn(SPEC_CHAR_NAME);
+
+ when(mMockCursor.getString(PHONEBOOK_LABEL_COLUMN)).thenReturn("");
+ when(mMockCursor.getString(PRIMARY_KEY_COLUMN)).thenReturn(SPEC_CHAR_NAME);
mSpecCharName = Contact.fromCursor(mMockContext, mMockCursor);
}
@Test
public void compareTo_TwoNullStrings_Equal() {
+ // NULL == NULL
int compareResult = mNullName.compareTo(mNullName);
assertEquals(COMPARE_RESULT_EQUAL, compareResult);
}
@Test
public void compareTo_TwoEmptyStrings_Equal() {
+ // "" == NULL
int compareResult = mEmptyName.compareTo(mEmptyName);
assertEquals(COMPARE_RESULT_EQUAL, compareResult);
}
@Test
public void compareTo_TwoLetterStrings_Larger() {
+ // "test" > "ta"
int compareResult = mLetterName1.compareTo(mLetterName2);
assertEquals(COMPARE_RESULT_LARGER, compareResult);
}
@Test
public void compareTo_TwoDigitStrings_Smaller() {
+ // "123" < "321"
int compareResult = mDigitName1.compareTo(mDigitName2);
assertEquals(COMPARE_RESULT_SMALLER, compareResult);
}
@Test
public void compareTo_LetterAndDigitStrings_Smaller() {
+ // "test" < "123", because of Phonebook_label
int compareResult = mLetterName1.compareTo(mDigitName1);
assertEquals(COMPARE_RESULT_SMALLER, compareResult);
}
@Test
public void compareTo_LetterAndSpecialCharStrings_Smaller() {
+ // "test" <"-", because of Phonebook_label
int compareResult = mLetterName1.compareTo(mSpecCharName);
assertEquals(COMPARE_RESULT_SMALLER, compareResult);
}
@Test
public void compareTo_LetterAndEmptyStrings_Smaller() {
+ // "test" < "", because of Phonebook_label
int compareResult = mLetterName1.compareTo(mEmptyName);
assertEquals(COMPARE_RESULT_SMALLER, compareResult);
}
@Test
public void compareTo_LetterAndNullStrings_Smaller() {
+ // "test < NULL, because of Phonebook_label
int compareResult = mLetterName1.compareTo(mNullName);
assertEquals(COMPARE_RESULT_SMALLER, compareResult);
}
@Test
public void compareTo_DigitAndSpecialCharStrings_Smaller() {
+ // "123" < "-", because of Phonebook_label
int compareResult = mDigitName1.compareTo(mSpecCharName);
assertEquals(COMPARE_RESULT_SMALLER, compareResult);
}
@Test
public void compareTo_DigitAndEmptyStrings_Smaller() {
+ // "123" > "", because of Phonebook_label
int compareResult = mDigitName1.compareTo(mEmptyName);
assertEquals(COMPARE_RESULT_SMALLER, compareResult);
}
@Test
public void compareTo_DigitAndNullStrings_Smaller() {
+ // "123" < NULL, because of Phonebook_label
int compareResult = mDigitName1.compareTo(mNullName);
assertEquals(COMPARE_RESULT_SMALLER, compareResult);
}
@Test
public void compareTo_SpecialCharAndEmptyStrings_Any() {
+ // "-" > ""
int compareResult = mSpecCharName.compareTo(mEmptyName);
assertThat(compareResult).isAnyOf(COMPARE_RESULT_SMALLER, COMPARE_RESULT_EQUAL,
COMPARE_RESULT_LARGER);
@@ -174,6 +210,7 @@
@Test
public void compareTo_SpecialCharAndNullStrings_Any() {
+ // "-" > NULL
int compareResult = mSpecCharName.compareTo(mNullName);
assertThat(compareResult).isAnyOf(COMPARE_RESULT_SMALLER, COMPARE_RESULT_EQUAL,
COMPARE_RESULT_LARGER);
@@ -181,24 +218,97 @@
@Test
public void compareTo_EmptyAndNullStrings_Equal() {
+ // "" == NULL
int compareResult = mEmptyName.compareTo(mNullName);
assertEquals(COMPARE_RESULT_EQUAL, compareResult);
}
@Test
public void sortContactTest() {
- List<Contact> sortResultList = new ArrayList<>();
- sortResultList.add(mLetterName2);
- sortResultList.add(mLetterName1);
- sortResultList.add(mDigitName1);
- sortResultList.add(mDigitName2);
- sortResultList.add(mEmptyName);
- sortResultList.add(mSpecCharName);
- List<Contact> contactList = new ArrayList<>();
- contactList.addAll(sortResultList);
+ List<Contact> expectedList = new ArrayList<>();
+ expectedList.add(mLetterName2);
+ expectedList.add(mLetterName1);
+ expectedList.add(mDigitName1);
+ expectedList.add(mDigitName2);
+ expectedList.add(mEmptyName);
+ expectedList.add(mSpecCharName);
- Collections.shuffle(contactList);
+ List<Contact> contactList = new ArrayList<>();
+ contactList.add(mDigitName1);
+ contactList.add(mSpecCharName);
+ contactList.add(mLetterName1);
+ contactList.add(mEmptyName);
+ contactList.add(mLetterName2);
+ contactList.add(mDigitName2);
+
Collections.sort(contactList);
- assertArrayEquals(sortResultList.toArray(), contactList.toArray());
+ assertArrayEquals(expectedList.toArray(), contactList.toArray());
+ }
+
+ @Test
+ public void sortContactPrimaryTest() {
+ when(mMockCursor.getString(PRIMARY_KEY_COLUMN)).thenReturn("tä");
+ Contact letterName3 = Contact.fromCursor(mMockContext, mMockCursor);
+
+ when(mMockCursor.getString(PRIMARY_KEY_COLUMN)).thenReturn("tb");
+ Contact letterName4 = Contact.fromCursor(mMockContext, mMockCursor);
+
+ List<Contact> expectedList = new ArrayList<>();
+ expectedList.add(mLetterName2);
+ expectedList.add(letterName3);
+ expectedList.add(letterName4);
+ expectedList.add(mLetterName1);
+ expectedList.add(mDigitName1);
+ expectedList.add(mDigitName2);
+ expectedList.add(mEmptyName);
+ expectedList.add(mSpecCharName);
+
+ List<Contact> contactList = new ArrayList<>();
+ contactList.add(mDigitName1);
+ contactList.add(letterName4);
+ contactList.add(mSpecCharName);
+ contactList.add(mLetterName1);
+ contactList.add(mEmptyName);
+ contactList.add(mLetterName2);
+ contactList.add(letterName3);
+ contactList.add(mDigitName2);
+
+ Collections.sort(contactList, (o1, o2) -> o1.compareBySortKeyPrimary(o2));
+ assertArrayEquals(expectedList.toArray(), contactList.toArray());
+ }
+
+ @Test
+ public void sortContactAlternativeTest() {
+ int alternativeColumnIndex = 20;
+ when(mMockCursor.getColumnIndex(ContactsContract.RawContacts.SORT_KEY_ALTERNATIVE))
+ .thenReturn(alternativeColumnIndex);
+ when(mMockCursor.getString(alternativeColumnIndex)).thenReturn("tä");
+ Contact letterName3 = Contact.fromCursor(mMockContext, mMockCursor);
+
+ when(mMockCursor.getString(alternativeColumnIndex)).thenReturn("tb");
+ Contact letterName4 = Contact.fromCursor(mMockContext, mMockCursor);
+
+ List<Contact> expectedList = new ArrayList<>();
+ expectedList.add(mLetterName2);
+ expectedList.add(letterName3);
+ expectedList.add(letterName4);
+ expectedList.add(mLetterName1);
+ expectedList.add(mDigitName1);
+ expectedList.add(mDigitName2);
+ expectedList.add(mEmptyName);
+ expectedList.add(mSpecCharName);
+
+ List<Contact> contactList = new ArrayList<>();
+ contactList.add(mDigitName1);
+ contactList.add(letterName4);
+ contactList.add(mSpecCharName);
+ contactList.add(mLetterName1);
+ contactList.add(mEmptyName);
+ contactList.add(mLetterName2);
+ contactList.add(letterName3);
+ contactList.add(mDigitName2);
+
+ Collections.sort(contactList, (o1, o2) -> o1.compareBySortKeyAlt(o2));
+ assertArrayEquals(expectedList.toArray(), contactList.toArray());
}
}
diff --git a/car-ui-lib/car-rotary-lib/OWNERS b/car-ui-lib/car-rotary-lib/OWNERS
index 2d2eaee..0439586 100644
--- a/car-ui-lib/car-rotary-lib/OWNERS
+++ b/car-ui-lib/car-rotary-lib/OWNERS
@@ -1 +1 @@
-include platform/packages/apps/Car/RotaryController/OWNERS
\ No newline at end of file
+include platform/packages/apps/Car/RotaryController:/OWNERS
\ No newline at end of file
diff --git a/car-ui-lib/car-ui-lib/build.gradle b/car-ui-lib/car-ui-lib/build.gradle
index b7368d8..478a739 100644
--- a/car-ui-lib/car-ui-lib/build.gradle
+++ b/car-ui-lib/car-ui-lib/build.gradle
@@ -83,14 +83,6 @@
api "androidx.asynclayoutinflater:asynclayoutinflater:1.0.0"
implementation 'com.android.support:support-annotations:28.0.0'
- testImplementation "androidx.test.ext:junit:1.1.2"
- testImplementation 'org.robolectric:robolectric:4.3.1'
- testImplementation "org.mockito:mockito-core:2.19.0"
- testImplementation "com.google.truth:truth:1.1.2"
- testImplementation "org.testng:testng:6.9.9"
- // Required for local unit tests (JUnit 4 framework)
- testImplementation 'junit:junit:4.13.2'
-
androidTestImplementation 'org.hamcrest:hamcrest-library:1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.3.0'
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/preference/PreferenceTest.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/preference/PreferenceTest.java
index 1a3d1cd..0866334 100644
--- a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/preference/PreferenceTest.java
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/preference/PreferenceTest.java
@@ -19,6 +19,7 @@
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.action.ViewActions.typeText;
+import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.isChecked;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
@@ -43,7 +44,10 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
import android.content.res.Resources;
+import android.view.View;
import androidx.preference.CheckBoxPreference;
import androidx.preference.DropDownPreference;
@@ -790,7 +794,7 @@
preference.setKey("editText");
preference.setTitle(R.string.title_edit_text_preference);
preference.setOrder(0);
- CharSequence positiveButtonText = "Ok";
+ String positiveButtonText = "Ok";
preference.setPositiveButtonText(positiveButtonText);
preference.setDialogTitle(R.string.dialog_title_edit_text_preference);
preference.setSummaryProvider(EditTextPreference.SimpleSummaryProvider.getInstance());
@@ -805,12 +809,12 @@
onView(withText(R.string.dialog_title_edit_text_preference)).check(matches(isDisplayed()));
// Enter value
- CharSequence value = "test value";
- onView(withId(android.R.id.edit)).perform(typeText(value.toString()));
- onView(withText(positiveButtonText.toString())).perform(click());
+ String value = "test value";
+ onView(withId(android.R.id.edit)).perform(typeText(value));
+ onView(withText(positiveButtonText)).perform(click());
// Confirm value updated by simple summary provider
- onView(withText(value.toString())).check(matches(isDisplayed()));
+ onView(withText(value)).check(matches(isDisplayed()));
}
@Test
@@ -849,9 +853,9 @@
preference.setKey("seek_bar");
preference.setTitle(R.string.title_seek_bar_preference);
preference.setOrder(0);
- CharSequence positiveButtonText = "Ok";
+ String positiveButtonText = "Ok";
preference.setPositiveButtonText(positiveButtonText);
- CharSequence negativeButtonText = "Cancel";
+ String negativeButtonText = "Cancel";
preference.setNegativeButtonText(negativeButtonText);
preference.setDialogTitle(R.string.dialog_title_seek_bar_preference);
preference.setMaxProgress(20);
@@ -863,8 +867,8 @@
// Click on preference
onView(withText(R.string.title_seek_bar_preference)).perform(click());
onView(withText(R.string.dialog_title_seek_bar_preference)).check(matches(isDisplayed()));
- onView(withText(positiveButtonText.toString())).check(matches(isDisplayed()));
- onView(withText(negativeButtonText.toString())).check(matches(isDisplayed()));
+ onView(withText(positiveButtonText)).check(matches(isDisplayed()));
+ onView(withText(negativeButtonText)).check(matches(isDisplayed()));
// Confirm progress is set to 0
assertEquals(0, preference.getProgress());
@@ -877,16 +881,91 @@
}
@Test
+ public void testSeekBarPreference_clickOk_valueSaved() {
+ // Create CarUiSeekBarDialogPreference preference and add it to screen.
+ CarUiSeekBarDialogPreference preference = new CarUiSeekBarDialogPreference(mActivity);
+ preference.setKey("seek_bar");
+ preference.setTitle(R.string.title_seek_bar_preference);
+ preference.setOrder(0);
+ String positiveButtonText = "Ok";
+ preference.setPositiveButtonText(positiveButtonText);
+ String negativeButtonText = "Cancel";
+ preference.setNegativeButtonText(negativeButtonText);
+ preference.setDialogTitle(R.string.dialog_title_seek_bar_preference);
+ preference.setMaxProgress(20);
+ mActivity.addPreference(preference);
+
+ // Check title is displayed as expected.
+ onView(withText(R.string.title_seek_bar_preference)).check(matches(isDisplayed()));
+
+ // Click on preference, set progress, then hit ok
+ onView(withText(R.string.title_seek_bar_preference)).perform(click());
+ onView(withId(R.id.seek_bar)).perform(setProgress(10));
+ onView(withText(positiveButtonText)).perform(click());
+ onView(withText(R.string.dialog_title_seek_bar_preference)).check(doesNotExist());
+
+ // Confirm progress is set to 0
+ assertEquals(10, preference.getProgress());
+ assertEquals(20, preference.getMaxProgress());
+ }
+
+ @Test
+ public void testSeekBarPreference_clickCancel_valueNotSaved() {
+ // Create CarUiSeekBarDialogPreference preference and add it to screen.
+ CarUiSeekBarDialogPreference preference = new CarUiSeekBarDialogPreference(mActivity);
+ preference.setKey("seek_bar");
+ preference.setTitle(R.string.title_seek_bar_preference);
+ preference.setOrder(0);
+ String positiveButtonText = "Ok";
+ preference.setPositiveButtonText(positiveButtonText);
+ String negativeButtonText = "Cancel";
+ preference.setNegativeButtonText(negativeButtonText);
+ preference.setDialogTitle(R.string.dialog_title_seek_bar_preference);
+ preference.setMaxProgress(20);
+ mActivity.addPreference(preference);
+
+ // Check title is displayed as expected.
+ onView(withText(R.string.title_seek_bar_preference)).check(matches(isDisplayed()));
+
+ // Click on preference, set progress, then hit cancel
+ onView(withText(R.string.title_seek_bar_preference)).perform(click());
+ onView(withId(R.id.seek_bar)).perform(setProgress(10));
+ onView(withText(negativeButtonText)).perform(click());
+ onView(withText(R.string.dialog_title_seek_bar_preference)).check(doesNotExist());
+
+ // Confirm progress is set to 0
+ assertEquals(0, preference.getProgress());
+ assertEquals(20, preference.getMaxProgress());
+ }
+
+ @Test
+ public void test_defaultDialogFragmentCallbacks_doNothing() {
+ DialogFragmentCallbacks callbacks = new DialogFragmentCallbacks() {
+ };
+
+ callbacks.onBindDialogView(new View(mActivity));
+ callbacks.onClick(new DialogInterface() {
+ @Override
+ public void cancel() {
+ }
+
+ @Override
+ public void dismiss() {
+ }
+ }, 0);
+ callbacks.onDialogClosed(true);
+ callbacks.onPrepareDialogBuilder(new AlertDialog.Builder(mActivity));
+ }
+
+ @Test
public void testSeekBarPreference_uxRestricted() {
// Create CarUiSeekBarDialogPreference preference and add it to screen.
CarUiSeekBarDialogPreference preference = new CarUiSeekBarDialogPreference(mActivity);
preference.setKey("seek_bar");
preference.setTitle(R.string.title_seek_bar_preference);
preference.setOrder(0);
- CharSequence positiveButtonText = "Ok";
- preference.setPositiveButtonText(positiveButtonText);
- CharSequence negativeButtonText = "Cancel";
- preference.setNegativeButtonText(negativeButtonText);
+ preference.setPositiveButtonText("Ok");
+ preference.setNegativeButtonText("Cancel");
preference.setDialogTitle(R.string.dialog_title_seek_bar_preference);
preference.setMaxProgress(20);
preference.setUxRestricted(true);
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/preference/PreferenceTestFragment.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/preference/PreferenceTestFragment.java
index 3797913..631911d 100644
--- a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/preference/PreferenceTestFragment.java
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/preference/PreferenceTestFragment.java
@@ -56,6 +56,7 @@
*/
public static class TestDataStore extends PreferenceDataStore {
+ private final Map<String, Integer> mIntStore = new HashMap<>();
private final Map<String, String> mStringStore = new HashMap<>();
private final Map<String, Boolean> mBooleanStore = new HashMap<>();
private final Map<String, Set<String>> mStringSetStore = new HashMap<>();
@@ -95,5 +96,15 @@
public boolean getBoolean(String key, boolean defValue) {
return mBooleanStore.getOrDefault(key, defValue);
}
+
+ @Override
+ public void putInt(String key, int value) {
+ mIntStore.put(key, value);
+ }
+
+ @Override
+ public int getInt(String key, int defValue) {
+ return mIntStore.getOrDefault(key, defValue);
+ }
}
}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/DelegatingContentLimitingAdapterTest.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/DelegatingContentLimitingAdapterTest.java
index 3908df8..b3ad0c1 100644
--- a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/DelegatingContentLimitingAdapterTest.java
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/DelegatingContentLimitingAdapterTest.java
@@ -21,12 +21,16 @@
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
import android.view.View;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.OrientationHelper;
+import androidx.recyclerview.widget.RecyclerView.AdapterDataObserver;
import androidx.test.core.app.ActivityScenario;
import androidx.test.ext.junit.rules.ActivityScenarioRule;
@@ -36,6 +40,7 @@
import org.junit.Rule;
import org.junit.Test;
+import java.util.ArrayList;
import java.util.Objects;
public class DelegatingContentLimitingAdapterTest {
@@ -127,4 +132,150 @@
onView(withText(mDelegateAdapter.getItemText(15))).check(matches(isDisplayed()));
}
+
+ @Test
+ public void testChangeItem_callsObservers() {
+ mDelegateAdapter = new TestDelegatingContentLimitingAdapter(50);
+ mContentLimitingAdapter = new DelegatingContentLimitingAdapter<>(mDelegateAdapter, 1);
+
+ AdapterDataObserver observer = mock(AdapterDataObserver.class);
+ mContentLimitingAdapter.registerAdapterDataObserver(observer);
+
+ onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+ CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+ mActivity.runOnUiThread(() -> {
+ carUiRecyclerView.setAdapter(mContentLimitingAdapter);
+ carUiRecyclerView.setVisibility(View.VISIBLE);
+ mContentLimitingAdapter.setMaxItems(10);
+ mDelegateAdapter.changeItemRange(5, 3);
+ });
+
+ onView(withText(mDelegateAdapter.getItemText(0))).check(matches(isDisplayed()));
+
+ verify(observer).onItemRangeChanged(5, 3, null);
+ }
+
+ @Test
+ public void testInsertItem_callsObservers() {
+ mDelegateAdapter = new TestDelegatingContentLimitingAdapter(50);
+ mContentLimitingAdapter = new DelegatingContentLimitingAdapter<>(mDelegateAdapter, 1);
+
+ AdapterDataObserver observer = mock(AdapterDataObserver.class);
+ mContentLimitingAdapter.registerAdapterDataObserver(observer);
+
+ onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+ CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+ mActivity.runOnUiThread(() -> {
+ carUiRecyclerView.setAdapter(mContentLimitingAdapter);
+ carUiRecyclerView.setVisibility(View.VISIBLE);
+ mContentLimitingAdapter.setMaxItems(10);
+ mDelegateAdapter.insertItemRange(5, "new item 1", "new item 2");
+ });
+
+ onView(withText(mDelegateAdapter.getItemText(0))).check(matches(isDisplayed()));
+
+ verify(observer).onItemRangeInserted(5, 2);
+ }
+
+ @Test
+ public void testRemoveItem_callsObservers() {
+ mDelegateAdapter = new TestDelegatingContentLimitingAdapter(50);
+ mContentLimitingAdapter = new DelegatingContentLimitingAdapter<>(mDelegateAdapter, 1);
+
+ AdapterDataObserver observer = mock(AdapterDataObserver.class);
+ mContentLimitingAdapter.registerAdapterDataObserver(observer);
+
+ onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+ CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+ mActivity.runOnUiThread(() -> {
+ carUiRecyclerView.setAdapter(mContentLimitingAdapter);
+ carUiRecyclerView.setVisibility(View.VISIBLE);
+ mContentLimitingAdapter.setMaxItems(10);
+ mDelegateAdapter.removeItemRange(5, 2);
+ });
+
+ onView(withText(mDelegateAdapter.getItemText(0))).check(matches(isDisplayed()));
+
+ verify(observer).onItemRangeRemoved(5, 2);
+ }
+
+ @Test
+ public void testMoveItem_callsObservers() {
+ mDelegateAdapter = new TestDelegatingContentLimitingAdapter(50);
+ mContentLimitingAdapter = new DelegatingContentLimitingAdapter<>(mDelegateAdapter, 1);
+
+ AdapterDataObserver observer = mock(AdapterDataObserver.class);
+ mContentLimitingAdapter.registerAdapterDataObserver(observer);
+
+ onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+ CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+ mActivity.runOnUiThread(() -> {
+ carUiRecyclerView.setAdapter(mContentLimitingAdapter);
+ carUiRecyclerView.setVisibility(View.VISIBLE);
+ mContentLimitingAdapter.setMaxItems(10);
+ mDelegateAdapter.moveItem(5, 2);
+ });
+
+ onView(withText(mDelegateAdapter.getItemText(0))).check(matches(isDisplayed()));
+
+ verify(observer).onChanged();
+ }
+
+ @Test
+ public void testChangeDataSet_callsObservers() {
+ mDelegateAdapter = new TestDelegatingContentLimitingAdapter(50);
+ mContentLimitingAdapter = new DelegatingContentLimitingAdapter<>(mDelegateAdapter, 1);
+
+ AdapterDataObserver observer = mock(AdapterDataObserver.class);
+ mContentLimitingAdapter.registerAdapterDataObserver(observer);
+
+ onView(withId(R.id.list)).check(matches(isDisplayed()));
+
+ CarUiRecyclerView carUiRecyclerView = mActivity.requireViewById(R.id.list);
+ mActivity.runOnUiThread(() -> {
+ carUiRecyclerView.setAdapter(mContentLimitingAdapter);
+ carUiRecyclerView.setVisibility(View.VISIBLE);
+ mContentLimitingAdapter.setMaxItems(10);
+ });
+
+ onView(withText(mDelegateAdapter.getItemText(0))).check(matches(isDisplayed()));
+
+ mActivity.runOnUiThread(() -> {
+ ArrayList<String> newItems = new ArrayList<>();
+ for (int i = 0; i < 40; i++) {
+ newItems.add("New Item " + i);
+ }
+ mDelegateAdapter.changeList(newItems);
+ });
+
+ onView(withText("New Item 0")).check(matches(isDisplayed()));
+
+ verify(observer).onChanged();
+ }
+
+ @Test
+ public void testSetHasStableId_setsDelegateToo() {
+ mDelegateAdapter = new TestDelegatingContentLimitingAdapter(50);
+ mDelegateAdapter.setHasStableIds(false);
+
+ mContentLimitingAdapter = new DelegatingContentLimitingAdapter<>(mDelegateAdapter, 1);
+
+ mContentLimitingAdapter.setHasStableIds(true);
+
+ assertTrue(mDelegateAdapter.hasStableIds());
+ }
+
+ @Test
+ public void testGetIds_callsDelegate() {
+ mDelegateAdapter = new TestDelegatingContentLimitingAdapter(50);
+ mContentLimitingAdapter = new DelegatingContentLimitingAdapter<>(mDelegateAdapter, 1);
+
+ for (int i = 0; i < 50; i++) {
+ assertEquals(mDelegateAdapter.getItemId(i), mContentLimitingAdapter.getItemId(i));
+ }
+ }
}
diff --git a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/TestDelegatingContentLimitingAdapter.java b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/TestDelegatingContentLimitingAdapter.java
index d3e9791..4a59c04 100644
--- a/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/TestDelegatingContentLimitingAdapter.java
+++ b/car-ui-lib/car-ui-lib/src/androidTest/java/com/android/car/ui/recyclerview/TestDelegatingContentLimitingAdapter.java
@@ -62,6 +62,45 @@
return "Item " + i;
}
+ public void changeItemRange(int positionStart, int itemCount) {
+ for (int i = 0; i < itemCount; i++) {
+ mItems.set(i + positionStart, mItems.get(i + positionStart) + "-changed");
+ }
+ notifyItemRangeChanged(positionStart, itemCount);
+ }
+
+ public void insertItemRange(int position, String... items) {
+ for (int i = 0; i < items.length; i++) {
+ mItems.add(position, items[i]);
+ }
+ notifyItemRangeInserted(position, items.length);
+ }
+
+ public void removeItemRange(int positionStart, int itemCount) {
+ for (int i = 0; i < itemCount; i++) {
+ mItems.remove(positionStart + i);
+ }
+ notifyItemRangeRemoved(positionStart, itemCount);
+ }
+
+ public void moveItem(int fromPosition, int toPosition) {
+ String item = mItems.get(fromPosition);
+ if (fromPosition > toPosition) {
+ mItems.remove(fromPosition);
+ mItems.add(toPosition, item);
+ } else {
+ mItems.add(toPosition, item);
+ mItems.remove(fromPosition);
+ }
+ notifyItemMoved(fromPosition, toPosition);
+ }
+
+ public void changeList(List<String> newItems) {
+ mItems.clear();
+ mItems.addAll(newItems);
+ notifyDataSetChanged();
+ }
+
static class WithContentLimiting extends TestDelegatingContentLimitingAdapter
implements DelegatingContentLimitingAdapter.ContentLimiting {
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/DelegatingContentLimitingAdapter.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/DelegatingContentLimitingAdapter.java
index c865b75..62d9feb 100644
--- a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/DelegatingContentLimitingAdapter.java
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/recyclerview/DelegatingContentLimitingAdapter.java
@@ -41,6 +41,8 @@
private final int mScrollingLimitedMessagePositionOffset;
@IdRes
private final int mConfigId;
+ @NonNull
+ private final Observer mAdapterDataObserver;
/**
* Provides the abilities to delegate {@link ContentLimitingAdapter} callback functions.
@@ -102,7 +104,24 @@
mConfigId = configId;
mScrollingLimitedMessageViewType = viewType;
mScrollingLimitedMessagePositionOffset = offset;
- mDelegate.registerAdapterDataObserver(new Observer());
+ mAdapterDataObserver = new Observer();
+ }
+
+ @Override
+ public void registerAdapterDataObserver(@NonNull RecyclerView.AdapterDataObserver observer) {
+ if (!hasObservers()) {
+ mDelegate.registerAdapterDataObserver(mAdapterDataObserver);
+ }
+ super.registerAdapterDataObserver(observer);
+ }
+
+ @Override
+ public void unregisterAdapterDataObserver(@NonNull RecyclerView.AdapterDataObserver observer) {
+ super.unregisterAdapterDataObserver(observer);
+
+ if (!hasObservers()) {
+ mDelegate.unregisterAdapterDataObserver(mAdapterDataObserver);
+ }
}
private class Observer extends RecyclerView.AdapterDataObserver {
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/sharedlibrarysupport/SharedLibraryFactoryAdapterV1.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/sharedlibrarysupport/SharedLibraryFactoryAdapterV1.java
index 9dfd214..730d2d8 100644
--- a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/sharedlibrarysupport/SharedLibraryFactoryAdapterV1.java
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/sharedlibrarysupport/SharedLibraryFactoryAdapterV1.java
@@ -71,15 +71,11 @@
* SharedLibraryFactory.
*/
public final class SharedLibraryFactoryAdapterV1 implements SharedLibraryFactory {
-
- private final Context mSharedLibContext;
-
SharedLibraryFactoryOEMV1 mOem;
SharedLibraryFactoryStub mFactoryStub;
public SharedLibraryFactoryAdapterV1(SharedLibraryFactoryOEMV1 oem, Context sharedLibContext) {
mOem = oem;
- mSharedLibContext = sharedLibContext;
mFactoryStub = new SharedLibraryFactoryStub(sharedLibContext);
mOem.setRotaryFactories(
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/TabAdapterV1.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/TabAdapterV1.java
index 8cee728..543a10d 100644
--- a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/TabAdapterV1.java
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/TabAdapterV1.java
@@ -16,48 +16,33 @@
package com.android.car.ui.toolbar;
-import android.graphics.drawable.Drawable;
-
import com.android.car.ui.sharedlibrary.oemapis.toolbar.TabOEMV1;
import java.util.function.Consumer;
@SuppressWarnings("AndroidJdkLibsChecker")
-class TabAdapterV1 implements TabOEMV1 {
+class TabAdapterV1 {
private final Tab mClientTab;
+ private final TabOEMV1 mSharedLibraryTab;
TabAdapterV1(Tab clientTab) {
mClientTab = clientTab;
+ Consumer<Tab> selectedListener = mClientTab.getSelectedListener();
+ mSharedLibraryTab = TabOEMV1.builder()
+ .setIcon(mClientTab.getIcon())
+ .setTitle(mClientTab.getText())
+ .setOnSelectedListener(selectedListener == null
+ ? null
+ : () -> selectedListener.accept(mClientTab))
+ .build();
}
public Tab getClientTab() {
return mClientTab;
}
- @Override
- public String getTitle() {
- return mClientTab.getText();
- }
-
- @Override
- public Drawable getIcon() {
- return mClientTab.getIcon();
- }
-
-
- @Override
- public Runnable getOnClickListener() {
- Consumer<Tab> selectedListener = mClientTab.getSelectedListener();
- if (selectedListener == null) {
- return null;
- } else {
- return () -> selectedListener.accept(mClientTab);
- }
- }
-
- @Override
- public boolean shouldTint() {
- return true;
+ public TabOEMV1 getSharedLibraryTab() {
+ return mSharedLibraryTab;
}
}
diff --git a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/ToolbarControllerAdapterV1.java b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/ToolbarControllerAdapterV1.java
index 981cf71..8742961 100644
--- a/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/ToolbarControllerAdapterV1.java
+++ b/car-ui-lib/car-ui-lib/src/main/java/com/android/car/ui/toolbar/ToolbarControllerAdapterV1.java
@@ -475,11 +475,19 @@
boolean gainingTabs = newAdapterState.hasTabs() && !oldAdapterState.hasTabs();
boolean losingTabs = !newAdapterState.hasTabs() && oldAdapterState.hasTabs();
if (gainingTabs) {
- mOemToolbar.setTabs(newAdapterState.getTabs(), newAdapterState.getSelectedTab());
+ mOemToolbar.setTabs(newAdapterState.getTabs()
+ .stream()
+ .map(TabAdapterV1::getSharedLibraryTab)
+ .collect(toList()),
+ newAdapterState.getSelectedTab());
} else if (losingTabs) {
mOemToolbar.setTabs(Collections.emptyList(), -1);
} else if (newAdapterState.hasTabs() && newAdapterState.getTabsDirty()) {
- mOemToolbar.setTabs(newAdapterState.getTabs(), newAdapterState.getSelectedTab());
+ mOemToolbar.setTabs(newAdapterState.getTabs()
+ .stream()
+ .map(TabAdapterV1::getSharedLibraryTab)
+ .collect(toList()),
+ newAdapterState.getSelectedTab());
} else if (newAdapterState.hasTabs()
&& newAdapterState.getSelectedTab() != oldAdapterState.getSelectedTab()) {
mOemToolbar.selectTab(newAdapterState.getSelectedTab(), true);
diff --git a/car-ui-lib/car-ui-lib/src/test/Android.bp b/car-ui-lib/car-ui-lib/src/test/Android.bp
deleted file mode 100644
index 2d1827c..0000000
--- a/car-ui-lib/car-ui-lib/src/test/Android.bp
+++ /dev/null
@@ -1,30 +0,0 @@
-//
-// Copyright (C) 2020 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.
-
-//###########################################################
-// CarUi lib just for Robolectric test target. #
-//###########################################################
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-android_app {
- name: "CarUiRobolectricTestApp",
- resource_dirs: ["res"],
- platform_apis: true,
- privileged: true,
- libs: ["android.car"],
- static_libs: ["car-ui-lib"],
-}
diff --git a/car-ui-lib/car-ui-lib/src/test/AndroidManifest.xml b/car-ui-lib/car-ui-lib/src/test/AndroidManifest.xml
deleted file mode 100644
index eb83765..0000000
--- a/car-ui-lib/car-ui-lib/src/test/AndroidManifest.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2020 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">
-</manifest>
diff --git a/car-ui-lib/car-ui-lib/src/test/java/Android.bp b/car-ui-lib/car-ui-lib/src/test/java/Android.bp
deleted file mode 100644
index a418f14..0000000
--- a/car-ui-lib/car-ui-lib/src/test/java/Android.bp
+++ /dev/null
@@ -1,31 +0,0 @@
-//
-// Copyright (C) 2020 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.
-
-//###############################################
-// Car Ui Robolectric test target. #
-//###############################################
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-android_robolectric_test {
- name: "CarUiRoboTests",
- srcs: ["**/*.java"],
- libs: [
- "android.car",
- "testng",
- ],
- instrumentation_for: "CarUiRobolectricTestApp",
-}
diff --git a/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/CarUiListItemTest.java b/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/CarUiListItemTest.java
deleted file mode 100644
index 344180a..0000000
--- a/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/CarUiListItemTest.java
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * 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.recyclerview;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-import android.content.Context;
-import android.view.View;
-import android.widget.CheckBox;
-import android.widget.Switch;
-import android.widget.TextView;
-
-import com.android.car.ui.R;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@RunWith(RobolectricTestRunner.class)
-public class CarUiListItemTest {
-
- private CarUiRecyclerView mListView;
- private Context mContext;
-
- @Mock
- CarUiContentListItem.OnCheckedChangeListener mOnCheckedChangeListener;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mContext = RuntimeEnvironment.application;
- mListView = new CarUiRecyclerViewImpl(mContext);
- }
-
- private CarUiListItemAdapter.ListItemViewHolder getListItemViewHolderAtPosition(int position) {
- return (CarUiListItemAdapter.ListItemViewHolder) mListView.findViewHolderForAdapterPosition(
- position);
- }
-
- private View getListItemTitleAtPosition(int position) {
- return getListItemViewHolderAtPosition(position).itemView
- .findViewById(R.id.car_ui_list_item_title);
- }
-
- private View getListItemBodyAtPosition(int position) {
- return getListItemViewHolderAtPosition(position).itemView
- .findViewById(R.id.car_ui_list_item_body);
- }
-
- private View getListItemIconContainerAtPosition(int position) {
- return getListItemViewHolderAtPosition(position).itemView
- .findViewById(R.id.car_ui_list_item_icon_container);
- }
-
- private View getListItemActionContainerAtPosition(int position) {
- return getListItemViewHolderAtPosition(position)
- .itemView.findViewById(R.id.action_container);
- }
-
- private Switch getListItemSwitchAtPosition(int position) {
- return getListItemViewHolderAtPosition(position).itemView
- .findViewById(R.id.car_ui_list_item_switch_widget);
- }
-
- private CheckBox getListItemCheckBoxAtPosition(int position) {
- return getListItemViewHolderAtPosition(position)
- .itemView.findViewById(R.id.car_ui_list_item_checkbox_widget);
- }
-
- private View getListItemIconAtPosition(int position) {
- return getListItemViewHolderAtPosition(position).itemView.findViewById(R.id.icon);
- }
-
- private CarUiListItemAdapter.HeaderViewHolder getHeaderViewHolderAtPosition(int position) {
- return (CarUiListItemAdapter.HeaderViewHolder) mListView.findViewHolderForAdapterPosition(
- position);
- }
-
- private TextView getHeaderViewHolderTitleAtPosition(int position) {
- return getHeaderViewHolderAtPosition(position).itemView
- .findViewById(R.id.car_ui_list_item_title);
- }
-
- private TextView getHeaderViewHolderBodyAtPosition(int position) {
- return getHeaderViewHolderAtPosition(position).itemView
- .findViewById(R.id.car_ui_list_item_body);
- }
-
- private void updateRecyclerViewAdapter(CarUiListItemAdapter adapter) {
- mListView.setAdapter(adapter);
-
- // Force CarUiRecyclerView and the nested RecyclerView to be laid out.
- mListView.measure(0, 0);
- mListView.layout(0, 0, 100, 10000);
-
- if (mListView != null) {
- mListView.measure(0, 0);
- mListView.layout(0, 0, 100, 10000);
- }
-
- // Required to init nested RecyclerView
- mListView.getViewTreeObserver().dispatchOnGlobalLayout();
- }
-
- @Test
- public void testItemVisibility_withTitle() {
- List<CarUiListItem> items = new ArrayList<>();
-
- CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
- item.setTitle("Test title");
- items.add(item);
-
- updateRecyclerViewAdapter(new CarUiListItemAdapter(items));
-
- assertThat(getListItemTitleAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(getListItemBodyAtPosition(0).getVisibility()).isNotEqualTo(View.VISIBLE);
- assertThat(getListItemIconContainerAtPosition(0).getVisibility())
- .isNotEqualTo(View.VISIBLE);
- assertThat(getListItemActionContainerAtPosition(0).getVisibility())
- .isNotEqualTo(View.VISIBLE);
- }
-
- @Test
- public void testItemVisibility_withTitle_withBody() {
- List<CarUiListItem> items = new ArrayList<>();
-
- CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
- item.setTitle("Test title");
- item.setBody("Test body");
- items.add(item);
-
- updateRecyclerViewAdapter(new CarUiListItemAdapter(items));
-
- assertThat(getListItemTitleAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(getListItemBodyAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(getListItemIconContainerAtPosition(0).getVisibility())
- .isNotEqualTo(View.VISIBLE);
- assertThat(getListItemActionContainerAtPosition(0).getVisibility())
- .isNotEqualTo(View.VISIBLE);
- }
-
- @Test
- public void testItemVisibility_withTitle_withIcon() {
- List<CarUiListItem> items = new ArrayList<>();
-
- CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.NONE);
- item.setTitle("Test title");
- item.setIcon(mContext.getDrawable(R.drawable.car_ui_icon_close));
- items.add(item);
-
- updateRecyclerViewAdapter(new CarUiListItemAdapter(items));
-
- assertThat(getListItemTitleAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(getListItemBodyAtPosition(0).getVisibility()).isNotEqualTo(View.VISIBLE);
- assertThat(getListItemIconContainerAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(getListItemIconAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(getListItemActionContainerAtPosition(0).getVisibility())
- .isNotEqualTo(View.VISIBLE);
- }
-
- @Test
- public void testItemVisibility_withTitle_withCheckbox() {
- List<CarUiListItem> items = new ArrayList<>();
-
- CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.CHECK_BOX);
- item.setTitle("Test title");
- items.add(item);
-
- updateRecyclerViewAdapter(new CarUiListItemAdapter(items));
-
- assertThat(getListItemTitleAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(getListItemBodyAtPosition(0).getVisibility()).isNotEqualTo(View.VISIBLE);
- assertThat(getListItemIconContainerAtPosition(0).getVisibility())
- .isNotEqualTo(View.VISIBLE);
- assertThat(getListItemActionContainerAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(getListItemSwitchAtPosition(0).getVisibility()).isNotEqualTo(View.VISIBLE);
- assertThat(getListItemCheckBoxAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(getListItemCheckBoxAtPosition(0).isChecked()).isEqualTo(false);
- }
-
- @Test
- public void testItemVisibility_withTitle_withBody_withSwitch() {
- List<CarUiListItem> items = new ArrayList<>();
-
- CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.SWITCH);
- item.setTitle("Test title");
- item.setBody("Body text");
- items.add(item);
-
- updateRecyclerViewAdapter(new CarUiListItemAdapter(items));
-
- assertThat(getListItemTitleAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(getListItemBodyAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(getListItemIconContainerAtPosition(0).getVisibility())
- .isNotEqualTo(View.VISIBLE);
- assertThat(getListItemActionContainerAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(getListItemSwitchAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(getListItemSwitchAtPosition(0).isChecked()).isEqualTo(false);
- assertThat(getListItemCheckBoxAtPosition(0).getVisibility()).isNotEqualTo(View.VISIBLE);
- }
-
- @Test
- public void testCheckedState_switch() {
- List<CarUiListItem> items = new ArrayList<>();
-
- CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.SWITCH);
- item.setTitle("Test title");
- item.setOnCheckedChangeListener(mOnCheckedChangeListener);
- item.setChecked(true);
- items.add(item);
-
- updateRecyclerViewAdapter(new CarUiListItemAdapter(items));
-
- Switch switchWidget = getListItemSwitchAtPosition(0);
-
- assertThat(switchWidget.isChecked()).isEqualTo(true);
- switchWidget.performClick();
- assertThat(switchWidget.isChecked()).isEqualTo(false);
- verify(mOnCheckedChangeListener, times(1))
- .onCheckedChanged(item, false);
- }
-
- @Test
- public void testCheckedState_checkbox() {
- List<CarUiListItem> items = new ArrayList<>();
-
- CarUiContentListItem item = new CarUiContentListItem(CarUiContentListItem.Action.CHECK_BOX);
- item.setTitle("Test title");
- item.setOnCheckedChangeListener(mOnCheckedChangeListener);
- items.add(item);
-
- updateRecyclerViewAdapter(new CarUiListItemAdapter(items));
-
- CheckBox checkBox = getListItemCheckBoxAtPosition(0);
-
- assertThat(checkBox.isChecked()).isEqualTo(false);
- checkBox.performClick();
- assertThat(checkBox.isChecked()).isEqualTo(true);
- verify(mOnCheckedChangeListener, times(1))
- .onCheckedChanged(item, true);
- }
-
- @Test
- public void testHeader_onlyTitle() {
- List<CarUiListItem> items = new ArrayList<>();
-
- CharSequence title = "Test header";
- CarUiHeaderListItem header = new CarUiHeaderListItem(title);
- items.add(header);
-
- updateRecyclerViewAdapter(new CarUiListItemAdapter(items));
-
- assertThat(getHeaderViewHolderTitleAtPosition(0).getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(getHeaderViewHolderTitleAtPosition(0).getText()).isEqualTo(title);
- assertThat(getHeaderViewHolderBodyAtPosition(0).getVisibility()).isNotEqualTo(View.VISIBLE);
- }
-
- @Test
- public void testHeader_titleAndBody() {
- List<CarUiListItem> items = new ArrayList<>();
-
- CharSequence title = "Test header";
- CharSequence body = "With body text";
-
- CarUiHeaderListItem header = new CarUiHeaderListItem(title, body);
- items.add(header);
-
- updateRecyclerViewAdapter(new CarUiListItemAdapter(items));
-
- TextView titleView = getHeaderViewHolderTitleAtPosition(0);
- TextView bodyView = getHeaderViewHolderBodyAtPosition(0);
-
- assertThat(titleView.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(titleView.getText()).isEqualTo(title);
- assertThat(bodyView.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(bodyView.getText()).isEqualTo(body);
- }
-}
diff --git a/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/CarUiRecyclerViewAdapterTest.java b/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/CarUiRecyclerViewAdapterTest.java
deleted file mode 100644
index 4d21851..0000000
--- a/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/CarUiRecyclerViewAdapterTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.recyclerview;
-
-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 org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class CarUiRecyclerViewAdapterTest {
-
- private Context mContext;
- private CarUiRecyclerViewAdapter mCarUiRecyclerViewAdapter;
-
- @Mock
- private ViewGroup mParent;
- @Mock
- private ViewGroup.LayoutParams mLayoutParams;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
-
- mContext = RuntimeEnvironment.application;
- mCarUiRecyclerViewAdapter = new CarUiRecyclerViewAdapter();
- }
-
- @Test
- public void getItemCount_shouldAlwaysBeOne() {
- assertThat(mCarUiRecyclerViewAdapter.getItemCount()).isEqualTo(1);
- }
-
- @Test
- public void onCreateViewHolder_frameLayoutNotNull() {
-
- when(mParent.getContext()).thenReturn(mContext);
- when(mParent.generateLayoutParams(any())).thenReturn(mLayoutParams);
-
- CarUiRecyclerViewAdapter.NestedRowViewHolder nestedRowViewHolder =
- mCarUiRecyclerViewAdapter.onCreateViewHolder(mParent, 0);
-
- assertThat(nestedRowViewHolder.frameLayout).isNotNull();
- }
-}
diff --git a/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/CarUiRecyclerViewTest.java b/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/CarUiRecyclerViewTest.java
deleted file mode 100644
index 1c8cc68..0000000
--- a/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/CarUiRecyclerViewTest.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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.recyclerview;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.view.LayoutInflater;
-import android.view.View;
-
-import androidx.recyclerview.widget.GridLayoutManager;
-import androidx.recyclerview.widget.LinearLayoutManager;
-
-import com.android.car.ui.R;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.Robolectric;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class CarUiRecyclerViewTest {
-
- private Context mContext;
- private View mView;
- private CarUiRecyclerView mCarUiRecyclerView;
- private Resources mResources;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mContext = RuntimeEnvironment.application;
- mResources = mContext.getResources();
- }
-
- @Test
- public void setAdapter_shouldInitializeLinearLayoutManager() {
- mView = LayoutInflater.from(mContext)
- .inflate(mResources.getIdentifier("test_linear_car_ui_recycler_view", "layout",
- mContext.getPackageName()), null);
-
- mCarUiRecyclerView = mView.findViewById(
- mResources.getIdentifier("test_prv", "id", mContext.getPackageName()));
-
- assertThat(mCarUiRecyclerView.getLayoutManager()).isInstanceOf(
- LinearLayoutManager.class);
- }
-
- @Test
- public void setAdapter_shouldInitializeGridLayoutManager() {
- mView = LayoutInflater.from(mContext)
- .inflate(mResources.getIdentifier("test_grid_car_ui_recycler_view", "layout",
- mContext.getPackageName()), null);
-
- mCarUiRecyclerView = mView.findViewById(
- mResources.getIdentifier("test_prv", "id", mContext.getPackageName()));
-
- assertThat(mCarUiRecyclerView.getLayoutManager()).isInstanceOf(
- GridLayoutManager.class);
- }
-
- @Test
- public void init_shouldContainRecyclerView() {
- mView = LayoutInflater.from(mContext)
- .inflate(mResources.getIdentifier("test_linear_car_ui_recycler_view", "layout",
- mContext.getPackageName()), null);
-
- mCarUiRecyclerView = mView.findViewById(
- mResources.getIdentifier("test_prv", "id", mContext.getPackageName()));
-
- assertThat(mCarUiRecyclerView).isNotNull();
- }
-
- @Test
- public void init_shouldHaveGridLayout() {
- mCarUiRecyclerView = new CarUiRecyclerViewImpl(mContext,
- Robolectric.buildAttributeSet()
- .addAttribute(R.attr.layoutStyle, "grid").build());
- assertThat(mCarUiRecyclerView.getLayoutManager()).isInstanceOf(
- GridLayoutManager.class);
- }
-}
diff --git a/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/CarUiSmoothScrollerTest.java b/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/CarUiSmoothScrollerTest.java
deleted file mode 100644
index c5dc78b..0000000
--- a/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/CarUiSmoothScrollerTest.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.recyclerview;
-
-import static androidx.recyclerview.widget.LinearSmoothScroller.SNAP_TO_START;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class CarUiSmoothScrollerTest {
-
- private Context mContext;
- private CarUiSmoothScroller mCarUiSmoothScroller;
-
- @Before
- public void setUp() {
- mContext = RuntimeEnvironment.application;
- mCarUiSmoothScroller = new CarUiSmoothScroller(mContext);
- }
-
- @Test
- public void calculateTimeForScrolling_shouldInitializeAllValues() {
- assertThat(mCarUiSmoothScroller.mMillisecondsPerInch).isNotEqualTo(0);
- assertThat(mCarUiSmoothScroller.mDecelerationTimeDivisor).isNotEqualTo(0);
- assertThat(mCarUiSmoothScroller.mMillisecondsPerPixel).isNotEqualTo(0);
- assertThat(mCarUiSmoothScroller.mInterpolator).isNotNull();
- assertThat(mCarUiSmoothScroller.mDensityDpi).isNotEqualTo(0);
- }
-
- @Test
- public void getVerticalSnapPreference_shouldReturnSnapToStart() {
- assertThat(mCarUiSmoothScroller.getVerticalSnapPreference()).isEqualTo(SNAP_TO_START);
- }
-
- @Test
- public void calculateTimeForScrolling_shouldReturnMultiplierOfMillisecondsPerPixel() {
- assertThat(mCarUiSmoothScroller.calculateTimeForScrolling(20)).isEqualTo(
- (int) Math.ceil(Math.abs(20) * mCarUiSmoothScroller.mMillisecondsPerPixel));
- }
-
- @Test
- public void calculateTimeForDeceleration_shouldReturnNotBeZero() {
- assertThat(mCarUiSmoothScroller.calculateTimeForDeceleration(20)).isNotEqualTo(0);
- }
-}
diff --git a/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/CarUiSnapHelperTest.java b/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/CarUiSnapHelperTest.java
deleted file mode 100644
index 62edd3d..0000000
--- a/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/CarUiSnapHelperTest.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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.recyclerview;
-
-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.View;
-
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class CarUiSnapHelperTest {
-
- private Context mContext;
- private CarUiSnapHelper mCarUiSnapHelper;
-
- @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;
-
- mCarUiSnapHelper = new CarUiSnapHelper(mContext);
-
- when(mRecyclerView.getContext()).thenReturn(mContext);
- mCarUiSnapHelper.attachToRecyclerView(mRecyclerView);
- }
-
- @Test
- public void calculateDistanceToFinalSnap_shouldReturnTopMarginDifference() {
- when(mRecyclerView.getLayoutManager()).thenReturn(mLayoutManager);
- when(mRecyclerView.isInTouchMode()).thenReturn(true);
- 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 = mCarUiSnapHelper.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 = mCarUiSnapHelper.calculateScrollDistance(0, 10);
-
- assertThat(distance[1]).isEqualTo(50);
- }
-}
diff --git a/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/DefaultScrollBarTest.java b/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/DefaultScrollBarTest.java
deleted file mode 100644
index 1cd59df..0000000
--- a/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/recyclerview/DefaultScrollBarTest.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * 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.recyclerview;
-
-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.view.LayoutInflater;
-import android.view.View;
-import android.widget.FrameLayout;
-
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.android.car.ui.R;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-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);
-
- View scrollView = LayoutInflater.from(mContext).inflate(
- R.layout.car_ui_recyclerview_scrollbar, null);
- mScrollBar.initialize(mRecyclerView, scrollView);
-
- // 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);
-
- View scrollView = LayoutInflater.from(mContext).inflate(
- R.layout.car_ui_recyclerview_scrollbar, null);
- mScrollBar.initialize(mRecyclerView, scrollView);
-
- 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);
-
- View scrollView = LayoutInflater.from(mContext).inflate(
- R.layout.car_ui_recyclerview_scrollbar, null);
- mScrollBar.initialize(mRecyclerView, scrollView);
-
- 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);
-
- View scrollView = LayoutInflater.from(mContext).inflate(
- R.layout.car_ui_recyclerview_scrollbar, null);
- mScrollBar.initialize(mRecyclerView, scrollView);
- mScrollBar.setPadding(10, 20);
-
- assertThat(scrollView.getPaddingTop()).isEqualTo(10);
- assertThat(scrollView.getPaddingBottom()).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/car-ui-lib/src/test/java/com/android/car/ui/utils/CarUxRestrictionsUtilTest.java b/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/utils/CarUxRestrictionsUtilTest.java
deleted file mode 100644
index ea62ee5..0000000
--- a/car-ui-lib/car-ui-lib/src/test/java/com/android/car/ui/utils/CarUxRestrictionsUtilTest.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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.utils;
-
-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;
-
-@RunWith(RobolectricTestRunner.class)
-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/car-ui-lib/src/test/res/drawable/test_ic_launcher.png b/car-ui-lib/car-ui-lib/src/test/res/drawable/test_ic_launcher.png
deleted file mode 100644
index 2af53a4..0000000
--- a/car-ui-lib/car-ui-lib/src/test/res/drawable/test_ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/car-ui-lib/car-ui-lib/src/test/res/layout/test_custom_view.xml b/car-ui-lib/car-ui-lib/src/test/res/layout/test_custom_view.xml
deleted file mode 100644
index 7a52259..0000000
--- a/car-ui-lib/car-ui-lib/src/test/res/layout/test_custom_view.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ 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.
- -->
-<androidx.constraintlayout.widget.ConstraintLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <TextView
- android:id="@+id/text_box_1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="Text Box 1"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintEnd_toStartOf="@id/text_box_2"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toBottomOf="parent"/>
-
- <TextView
- android:id="@+id/text_box_2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="Text Box 2"
- app:layout_constraintStart_toEndOf="@id/text_box_1"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintBottom_toBottomOf="parent"/>
-
-
-</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/car-ui-lib/car-ui-lib/src/test/res/layout/test_grid_car_ui_recycler_view.xml b/car-ui-lib/car-ui-lib/src/test/res/layout/test_grid_car_ui_recycler_view.xml
deleted file mode 100644
index e5bf7a3..0000000
--- a/car-ui-lib/car-ui-lib/src/test/res/layout/test_grid_car_ui_recycler_view.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?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.
- -->
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <com.android.car.ui.recyclerview.CarUiRecyclerView
- android:id="@+id/test_prv"
- app:layoutStyle="grid"
- app:numOfColumns="4"
- android:layout_width="match_parent"
- android:layout_height="match_parent"/>
-</FrameLayout>
diff --git a/car-ui-lib/car-ui-lib/src/test/res/layout/test_linear_car_ui_recycler_view.xml b/car-ui-lib/car-ui-lib/src/test/res/layout/test_linear_car_ui_recycler_view.xml
deleted file mode 100644
index 8f7f2ad..0000000
--- a/car-ui-lib/car-ui-lib/src/test/res/layout/test_linear_car_ui_recycler_view.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?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.
- -->
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <com.android.car.ui.recyclerview.CarUiRecyclerView
- android:id="@+id/test_prv"
- android:layout_width="match_parent"
- android:layout_height="match_parent"/>
-</FrameLayout>
diff --git a/car-ui-lib/oem-apis/src/main/java/com/android/car/ui/sharedlibrary/oemapis/InsetsOEMV1.java b/car-ui-lib/oem-apis/src/main/java/com/android/car/ui/sharedlibrary/oemapis/InsetsOEMV1.java
index 11421a8..0e501d6 100644
--- a/car-ui-lib/oem-apis/src/main/java/com/android/car/ui/sharedlibrary/oemapis/InsetsOEMV1.java
+++ b/car-ui-lib/oem-apis/src/main/java/com/android/car/ui/sharedlibrary/oemapis/InsetsOEMV1.java
@@ -15,17 +15,64 @@
*/
package com.android.car.ui.sharedlibrary.oemapis;
+import java.util.Objects;
+
/**
* Represents insets in the base layout. {@link com.android.car.ui.baselayout.Insets} for more
* information.
*/
-public interface InsetsOEMV1 {
- /** Gets the left inset */
- int getLeft();
- /** Gets the right inset */
- int getRight();
- /** Gets the top inset */
- int getTop();
- /** Gets the bottom inset */
- int getBottom();
+public final class InsetsOEMV1 {
+ private final int mLeft;
+ private final int mRight;
+ private final int mTop;
+ private final int mBottom;
+
+ public InsetsOEMV1() {
+ mLeft = mRight = mTop = mBottom = 0;
+ }
+
+ public InsetsOEMV1(int left, int top, int right, int bottom) {
+ mLeft = left;
+ mRight = right;
+ mTop = top;
+ mBottom = bottom;
+ }
+
+ public int getLeft() {
+ return mLeft;
+ }
+
+ public int getRight() {
+ return mRight;
+ }
+
+ public int getTop() {
+ return mTop;
+ }
+
+ public int getBottom() {
+ return mBottom;
+ }
+
+ @Override
+ public String toString() {
+ return "{ left: " + mLeft + ", right: " + mRight
+ + ", top: " + mTop + ", bottom: " + mBottom + " }";
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ InsetsOEMV1 insets = (InsetsOEMV1) o;
+ return mLeft == insets.mLeft
+ && mRight == insets.mRight
+ && mTop == insets.mTop
+ && mBottom == insets.mBottom;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mLeft, mRight, mTop, mBottom);
+ }
}
diff --git a/car-ui-lib/oem-apis/src/main/java/com/android/car/ui/sharedlibrary/oemapis/toolbar/TabOEMV1.java b/car-ui-lib/oem-apis/src/main/java/com/android/car/ui/sharedlibrary/oemapis/toolbar/TabOEMV1.java
index 9db4423..d175aca 100644
--- a/car-ui-lib/oem-apis/src/main/java/com/android/car/ui/sharedlibrary/oemapis/toolbar/TabOEMV1.java
+++ b/car-ui-lib/oem-apis/src/main/java/com/android/car/ui/sharedlibrary/oemapis/toolbar/TabOEMV1.java
@@ -19,17 +19,85 @@
import android.graphics.drawable.Drawable;
/** Interface representing a toolbar tab */
-public interface TabOEMV1 {
+public final class TabOEMV1 {
+ private final String mTitle;
+ private final Drawable mIcon;
+ private final Runnable mOnSelectedListener;
+ private final boolean mTinted;
+
+ private TabOEMV1(Builder builder) {
+ mTitle = builder.mTitle;
+ mIcon = builder.mIcon;
+ mOnSelectedListener = builder.mOnSelectedListener;
+ mTinted = builder.mTinted;
+ }
+
+ /** Constructs a new {@link Builder} to build a tab with */
+ public static Builder builder() {
+ return new Builder();
+ }
+
/** Gets the title of the tab */
- String getTitle();
+ public String getTitle() {
+ return mTitle;
+ }
+
/** Gets the icon of the tab. The icon may be tinted to match the theme of the toolbar */
- Drawable getIcon();
+ public Drawable getIcon() {
+ return mIcon;
+ }
+
/** Gets the function to call when the tab is selected */
- Runnable getOnClickListener();
+ public Runnable getOnSelectedListener() {
+ return mOnSelectedListener;
+ }
+
/**
* Returns if the icon should be tinted to match the style of the toolbar.
* Most of the time this will be true. If not, then the original colors of the drawable
* should be shown.
*/
- boolean shouldTint();
+ public boolean isTinted() {
+ return mTinted;
+ }
+
+ /** Builder for {@link TabOEMV1} */
+ public static class Builder {
+ private String mTitle = null;
+ private Drawable mIcon = null;
+ private Runnable mOnSelectedListener = null;
+ private boolean mTinted = true;
+
+ private Builder() {
+ }
+
+ /** Sets the tab's text */
+ public Builder setTitle(String title) {
+ mTitle = title;
+ return this;
+ }
+
+ /** Sets the tab's icon */
+ public Builder setIcon(Drawable icon) {
+ mIcon = icon;
+ return this;
+ }
+
+ /** Sets a listener that is called when the tab is selected */
+ public Builder setOnSelectedListener(Runnable callback) {
+ mOnSelectedListener = callback;
+ return this;
+ }
+
+ /** See {@link TabOEMV1#isTinted} */
+ public Builder setTinted(boolean tinted) {
+ mTinted = tinted;
+ return this;
+ }
+
+ /** Builds the final {@link TabOEMV1} */
+ public TabOEMV1 build() {
+ return new TabOEMV1(this);
+ }
+ }
}
diff --git a/car-ui-lib/referencedesign/sharedlibrary/Android.bp b/car-ui-lib/referencedesign/sharedlibrary/Android.bp
index 25b8276..384b741 100644
--- a/car-ui-lib/referencedesign/sharedlibrary/Android.bp
+++ b/car-ui-lib/referencedesign/sharedlibrary/Android.bp
@@ -2,6 +2,11 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
+android_app_certificate {
+ name: "car-ui-lib-sharedlibrary-certificate",
+ certificate: "chassis_upload_key"
+}
+
android_app {
name: "car-ui-lib-sharedlibrary",
@@ -27,4 +32,6 @@
optimize: {
enabled: false,
},
+
+ certificate: ":car-ui-lib-sharedlibrary-certificate",
}
diff --git a/car-ui-lib/referencedesign/sharedlibrary/build.gradle b/car-ui-lib/referencedesign/sharedlibrary/build.gradle
index 843f38a..99e0b1d 100644
--- a/car-ui-lib/referencedesign/sharedlibrary/build.gradle
+++ b/car-ui-lib/referencedesign/sharedlibrary/build.gradle
@@ -33,16 +33,15 @@
// In order to adb install a new version of an app over it's preinstalled version, the new
// version must be signed with the same key as the preinstalled version. If you don't specify
- // a certificate in the Android.bp file (which we don't), the default certificate that will
+ // a certificate in the Android.bp file, the default certificate that will
// be used is build/target/product/security/testkey.{pk8,x509.pem}. Android studio doesn't
// support signing apps using individual pk8 and x509.pem files, it requires a keystore file.
- // So the keystore in this project is just a repackaging of the testkey key.
signingConfigs {
debug {
- storeFile file('keystore')
- storePassword 'android'
- keyAlias 'testkey'
- keyPassword 'android'
+ storeFile file('chassis_upload_key.pepk')
+ storePassword 'chassis'
+ keyAlias 'chassis'
+ keyPassword 'chassis'
}
}
}
diff --git a/car-ui-lib/referencedesign/sharedlibrary/chassis_upload_key.pepk b/car-ui-lib/referencedesign/sharedlibrary/chassis_upload_key.pepk
new file mode 100644
index 0000000..b765db1
--- /dev/null
+++ b/car-ui-lib/referencedesign/sharedlibrary/chassis_upload_key.pepk
Binary files differ
diff --git a/car-ui-lib/referencedesign/sharedlibrary/chassis_upload_key.pk8 b/car-ui-lib/referencedesign/sharedlibrary/chassis_upload_key.pk8
new file mode 100644
index 0000000..a867fdd
--- /dev/null
+++ b/car-ui-lib/referencedesign/sharedlibrary/chassis_upload_key.pk8
Binary files differ
diff --git a/car-ui-lib/referencedesign/sharedlibrary/chassis_upload_key.x509.pem b/car-ui-lib/referencedesign/sharedlibrary/chassis_upload_key.x509.pem
new file mode 100644
index 0000000..027a197
--- /dev/null
+++ b/car-ui-lib/referencedesign/sharedlibrary/chassis_upload_key.x509.pem
@@ -0,0 +1,18 @@
+-----BEGIN CERTIFICATE-----
+MIIC9zCCAd+gAwIBAgIELMWXmDANBgkqhkiG9w0BAQsFADAsMQswCQYDVQQGEwJV
+UzELMAkGA1UECBMCQ0ExEDAOBgNVBAMTB0NoYXNzaXMwHhcNMjEwNTAzMTg1NDM5
+WhcNNDYwNDI3MTg1NDM5WjAsMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExEDAO
+BgNVBAMTB0NoYXNzaXMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCp
+JPZiygVOD1LEz+Hw3hS3SfCpqm5l57lje9K6hYqXN31l2xUsHaTBdz1w4AOTZgjm
+UQaY2m73HxMtOAli9OJUY6594orGYJS5dKqkuAnmMP4sCxvHRQvA413JERaKHXSz
+sg6AMkzOzPnTPqr+L2N013GaDj3knrz/7xKDvTJbHGVbPbogEDLZUs9hH7N8k03I
+jeU0ThDJpd2oJ/vzpv2bdV89gFmYAzu5hw+v1O2yPVf+OEsbL1kY+rJTmhTldtWJ
+/OPjHQQU/IV3TtQzy1xwEAsXC8M69VgoeGSBmQOo7tswuOMKngJ9OU8y0qFjbVUm
+xlwGix8nI6GxNlULrmSdAgMBAAGjITAfMB0GA1UdDgQWBBTkNQPmsZZ8KAjxOKXu
+u1fVHWWT7DANBgkqhkiG9w0BAQsFAAOCAQEAPQrN4tUM1lc40DsrMdAoSg7MZ0ji
+KOfGAjnPezJDqJY1fxoB4jRDd+ut13YiBFcnpH1LsJTekhkxLcL6mdCSOJO4f9UK
+YP/eMRS1tI5r/903qtdStzlYrBp+AKXicSV2q2Zr25AhZsFqDPR211xcKQNrmml1
+slCBK53Llk3wi795Disu1IlCsNN0CR4RmHAGOjZUU3QTNYyE6RhD3cdHZyzy0utt
+BkADfLvT7MCGHETDh1fvsNaieRzasV9dK30PTdQ8itj9+xel0cUnXTAXGs9YpudJ
+6ynTWXHZMU3N8Ay1Ip9d+J5pDSl//JXCSGFzVA3vO07AfUscQbtRoA/6lg==
+-----END CERTIFICATE-----
diff --git a/car-ui-lib/referencedesign/sharedlibrary/keystore b/car-ui-lib/referencedesign/sharedlibrary/keystore
deleted file mode 100644
index 49e4ecc..0000000
--- a/car-ui-lib/referencedesign/sharedlibrary/keystore
+++ /dev/null
Binary files differ
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 602777a..e5dcb80 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
@@ -150,7 +150,7 @@
private Consumer<InsetsOEMV1> mInsetsChangedListenerDelegate;
private boolean mInsetsDirty = true;
- private InsetsOEMV1 mInsets = new Insets();
+ private InsetsOEMV1 mInsets = new InsetsOEMV1();
/**
* Constructs an InsetsUpdater that calculates and dispatches insets to the method provided
@@ -253,7 +253,7 @@
right += Math.max(0,
getRightOfView(mContentViewContainer) - getLeftOfView(mRightInsetView));
}
- InsetsOEMV1 insets = new Insets(left, top, right, bottom);
+ InsetsOEMV1 insets = new InsetsOEMV1(left, top, right, bottom);
mInsetsDirty = false;
if (!insets.equals(mInsets)) {
diff --git a/car-ui-lib/referencedesign/sharedlibrary/src/main/java/com/chassis/car/ui/sharedlibrary/toolbar/Insets.java b/car-ui-lib/referencedesign/sharedlibrary/src/main/java/com/chassis/car/ui/sharedlibrary/toolbar/Insets.java
deleted file mode 100644
index 7b27a24..0000000
--- a/car-ui-lib/referencedesign/sharedlibrary/src/main/java/com/chassis/car/ui/sharedlibrary/toolbar/Insets.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.chassis.car.ui.sharedlibrary.toolbar;
-
-import com.android.car.ui.sharedlibrary.oemapis.InsetsOEMV1;
-
-import java.util.Objects;
-
-class Insets implements InsetsOEMV1 {
- private final int mLeft;
- private final int mRight;
- private final int mTop;
- private final int mBottom;
-
- Insets() {
- mLeft = mRight = mTop = mBottom = 0;
- }
-
- Insets(int left, int top, int right, int bottom) {
- mLeft = left;
- mRight = right;
- mTop = top;
- mBottom = bottom;
- }
-
- @Override
- public int getLeft() {
- return mLeft;
- }
-
- @Override
- public int getRight() {
- return mRight;
- }
-
- @Override
- public int getTop() {
- return mTop;
- }
-
- @Override
- public int getBottom() {
- return mBottom;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- Insets insets = (Insets) o;
- return mLeft == insets.mLeft
- && mRight == insets.mRight
- && mTop == insets.mTop
- && mBottom == insets.mBottom;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(mLeft, mRight, mTop, mBottom);
- }
-}
diff --git a/car-ui-lib/referencedesign/sharedlibrary/src/main/java/com/chassis/car/ui/sharedlibrary/toolbar/TabLayout.java b/car-ui-lib/referencedesign/sharedlibrary/src/main/java/com/chassis/car/ui/sharedlibrary/toolbar/TabLayout.java
index 25168d7..868193d 100644
--- a/car-ui-lib/referencedesign/sharedlibrary/src/main/java/com/chassis/car/ui/sharedlibrary/toolbar/TabLayout.java
+++ b/car-ui-lib/referencedesign/sharedlibrary/src/main/java/com/chassis/car/ui/sharedlibrary/toolbar/TabLayout.java
@@ -112,9 +112,9 @@
bindTab(oldSelectedTab);
bindTab(mSelectedTab);
- Runnable onClickListener = tab.getOnClickListener();
- if (onClickListener != null && sendCallback) {
- onClickListener.run();
+ Runnable onSelectedListener = tab.getOnSelectedListener();
+ if (onSelectedListener != null && sendCallback) {
+ onSelectedListener.run();
}
}