Merge "[WebView Support Library] Implement onReceivedError" into pi-androidx-dev
diff --git a/buildSrc/src/main/kotlin/androidx/build/SupportAndroidLibraryPlugin.kt b/buildSrc/src/main/kotlin/androidx/build/SupportAndroidLibraryPlugin.kt
index dd2e6da..e3458a5 100644
--- a/buildSrc/src/main/kotlin/androidx/build/SupportAndroidLibraryPlugin.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/SupportAndroidLibraryPlugin.kt
@@ -65,6 +65,20 @@
VersionFileWriterTask.setUpAndroidLibrary(project, library)
DiffAndDocs.registerAndroidProject(project, library, supportLibraryExtension)
+
+ library.libraryVariants.all { libraryVariant ->
+ if (libraryVariant.getBuildType().getName().equals("debug")) {
+ @Suppress("DEPRECATION")
+ val javaCompile = libraryVariant.javaCompile
+ if (supportLibraryExtension.failOnUncheckedWarnings) {
+ javaCompile.options.compilerArgs.add("-Xlint:unchecked")
+ }
+ if (supportLibraryExtension.failOnDeprecationWarnings) {
+ javaCompile.options.compilerArgs.add("-Xlint:deprecation")
+ }
+ javaCompile.options.compilerArgs.add("-Werror")
+ }
+ }
}
project.apply(mapOf("plugin" to "com.android.library"))
diff --git a/buildSrc/src/main/kotlin/androidx/build/SupportLibraryExtension.kt b/buildSrc/src/main/kotlin/androidx/build/SupportLibraryExtension.kt
index 4f69460..98528bb 100644
--- a/buildSrc/src/main/kotlin/androidx/build/SupportLibraryExtension.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/SupportLibraryExtension.kt
@@ -34,6 +34,9 @@
private var licenses: MutableCollection<License> = ArrayList()
var java8Library = false
var publish = false
+ var failOnUncheckedWarnings = true
+ var failOnDeprecationWarnings = true
+
/**
* This flag works only if publish flag is "true".
* It is useful for modules that are used for tooling. For example room annotation
diff --git a/car/api/current.txt b/car/api/current.txt
index 0aee549..471aa63 100644
--- a/car/api/current.txt
+++ b/car/api/current.txt
@@ -386,6 +386,8 @@
method public void setSupplementalEmptyIcon(boolean);
method public void setSupplementalIcon(int, boolean);
method public void setSupplementalIcon(int, boolean, android.view.View.OnClickListener);
+ method public void setSupplementalIcon(android.graphics.drawable.Drawable, boolean);
+ method public void setSupplementalIcon(android.graphics.drawable.Drawable, boolean, android.view.View.OnClickListener);
}
public static class SeekbarListItem.ViewHolder extends androidx.car.widget.ListItem.ViewHolder {
@@ -436,7 +438,9 @@
method public void setPrimaryActionIcon(android.graphics.drawable.Drawable, boolean);
method public void setPrimaryActionNoIcon();
method public void setSupplementalIcon(int, boolean);
+ method public void setSupplementalIcon(android.graphics.drawable.Drawable, boolean);
method public void setSupplementalIcon(int, boolean, android.view.View.OnClickListener);
+ method public void setSupplementalIcon(android.graphics.drawable.Drawable, boolean, android.view.View.OnClickListener);
method public void setSwitch(boolean, boolean, android.widget.CompoundButton.OnCheckedChangeListener);
method public void setSwitchState(boolean);
method public void setTitle(java.lang.String);
diff --git a/car/build.gradle b/car/build.gradle
index 52d2a40..d2e9be6 100644
--- a/car/build.gradle
+++ b/car/build.gradle
@@ -9,7 +9,8 @@
dependencies {
api project(':appcompat')
api project(':cardview')
- api "com.android.temp.support:design-widget:28.0.0-alpha1", {
+ api "com.android.temp.support:design-widget:28.0.0-alpha1@aar", {
+ transitive = true
exclude group: 'androidx.annotation'
exclude group: 'androidx.core'
exclude group: 'androidx.legacy'
@@ -54,4 +55,5 @@
description = "Android Car Support UI"
java8Library = true
minSdkVersion = 24
+ failOnUncheckedWarnings = false
}
diff --git a/car/res/layout/car_alert_dialog.xml b/car/res/layout/car_alert_dialog.xml
index d9b52a5..46da691 100644
--- a/car/res/layout/car_alert_dialog.xml
+++ b/car/res/layout/car_alert_dialog.xml
@@ -28,7 +28,7 @@
<LinearLayout
android:id="@+id/content_view"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/car_keyline_1"
android:layout_marginEnd="@dimen/car_keyline_1"
diff --git a/car/res/values-h1752dp/dimens.xml b/car/res/values-h1752dp/dimens.xml
index ea5ebd6..8b83972 100644
--- a/car/res/values-h1752dp/dimens.xml
+++ b/car/res/values-h1752dp/dimens.xml
@@ -23,18 +23,25 @@
<dimen name="car_body2_size">32sp</dimen>
<dimen name="car_label1_size">32sp</dimen>
<dimen name="car_action1_size">32sp</dimen>
+ <dimen name="car_action2_size">32sp</dimen>
+
+ <!-- Navigation Bar -->
+ <dimen name="car_navigation_bar_height">128dp</dimen>
<!-- Icons and Buttons -->
<!-- Icons -->
<dimen name="car_primary_icon_size">56dp</dimen>
<dimen name="car_secondary_icon_size">36dp</dimen>
- <!-- Avatars -->
- <dimen name="car_avatar_size">96dp</dimen>
+ <!-- Buttons -->
+ <dimen name="car_pill_button_size">76dp</dimen>
<!-- Minimum touch target size. -->
<dimen name="car_touch_target_size">96dp</dimen>
+ <!-- Status Bar -->
+ <dimen name="car_status_bar_height">56dp</dimen>
+
<!-- Application Bar -->
<dimen name="car_app_bar_height">112dp</dimen>
@@ -50,4 +57,7 @@
<!-- Sub Header -->
<dimen name="car_sub_header_height">96dp</dimen>
+
+ <!-- The height of a vertical line divider. -->
+ <dimen name="car_vertical_line_divider_height">96dp</dimen>
</resources>
diff --git a/car/res/values-h668dp/dimens.xml b/car/res/values-h668dp/dimens.xml
index ab0f120..46dfd27 100644
--- a/car/res/values-h668dp/dimens.xml
+++ b/car/res/values-h668dp/dimens.xml
@@ -24,10 +24,17 @@
<!-- Type Sizings -->
<dimen name="car_headline2_size">36sp</dimen>
+ <!-- Icons and Buttons -->
+ <!-- Icons -->
+ <dimen name="car_secondary_icon_size">36dp</dimen>
+
<!-- Car Component Dimensions -->
<!-- Application Bar -->
<dimen name="car_app_bar_height">96dp</dimen>
+ <!-- Action Bar -->
+ <dimen name="car_action_bar_height">128dp</dimen>
+
<!-- List Items -->
<dimen name="car_single_line_list_item_height">116dp</dimen>
@@ -41,4 +48,7 @@
<dimen name="car_drawer_list_item_icon_size">108dp</dimen>
<dimen name="car_drawer_list_item_small_icon_size">56dp</dimen>
<dimen name="car_drawer_list_item_end_icon_size">56dp</dimen>
+
+ <!-- The height of a vertical line divider. -->
+ <dimen name="car_vertical_line_divider_height">76dp</dimen>
</resources>
diff --git a/car/res/values-w1280dp/dimens.xml b/car/res/values-w1280dp/dimens.xml
index 418e51f..4003ac0 100644
--- a/car/res/values-w1280dp/dimens.xml
+++ b/car/res/values-w1280dp/dimens.xml
@@ -21,4 +21,7 @@
<!-- Keylines -->
<dimen name="car_keyline_4">182dp</dimen>
<dimen name="car_keyline_4_neg">-182dp</dimen>
+
+ <!-- Drawer Max Width -->
+ <dimen name="car_drawer_max_width">1200dp</dimen>
</resources>
diff --git a/car/res/values-w690dp/integers.xml b/car/res/values-w690dp/integers.xml
index 0eb5837..77a164a 100644
--- a/car/res/values-w690dp/integers.xml
+++ b/car/res/values-w690dp/integers.xml
@@ -23,8 +23,11 @@
<integer name="column_card_default_column_span">12</integer>
<!-- Dialogs -->
- <integer name="car_dialog_column_number">10</integer>
+ <integer name="car_dialog_column_number">12</integer>
<!-- Slide Up Menu -->
<integer name="car_slide_up_menu_column_number">12</integer>
+
+ <!-- Slide Down Menu -->
+ <integer name="car_slide_down_menu_column_number">12</integer>
</resources>
diff --git a/car/res/values-w930dp/dimens.xml b/car/res/values-w930dp/dimens.xml
index 0e68594..0fd925b 100644
--- a/car/res/values-w930dp/dimens.xml
+++ b/car/res/values-w930dp/dimens.xml
@@ -29,4 +29,7 @@
<dimen name="car_keyline_4_neg">-168dp</dimen>
<!-- The diff between keyline 1 and keyline 3. -->
<dimen name="car_keyline_1_keyline_3_diff">96dp</dimen>
+
+ <!-- Grid Spacing -->
+ <dimen name="car_grid_spacing_minimum">32dp</dimen>
</resources>
diff --git a/car/res/values/colors.xml b/car/res/values/colors.xml
index a6fb6be..4a76c32 100644
--- a/car/res/values/colors.xml
+++ b/car/res/values/colors.xml
@@ -32,11 +32,10 @@
<color name="car_white_1000">#1effffff</color>
<color name="car_blue_grey_800">#ff37474F</color>
<color name="car_blue_grey_900">#ff263238</color>
- <color name="car_dark_blue_grey_600">#ff1d272d</color>
+ <color name="car_dark_blue_grey_600">#ff222B31</color>
<color name="car_dark_blue_grey_700">#ff172026</color>
<color name="car_dark_blue_grey_800">#ff11181d</color>
- <color name="car_dark_blue_grey_900">#ff0c1013</color>
- <color name="car_dark_blue_grey_1000">#ff090c0f</color>
+ <color name="car_dark_blue_grey_900">#ff090C0F</color>
<color name="car_light_blue_300">#ff4fc3f7</color>
<color name="car_light_blue_500">#ff03A9F4</color>
<color name="car_light_blue_600">#ff039be5</color>
@@ -175,7 +174,7 @@
<!-- The inverted color of the seekbar track background. This color is always the opposite of
car_seekbar_track_background. -->
- <color name="car_seekbar_track_background_inverse"> @color/car_seekbar_track_background_light
+ <color name="car_seekbar_track_background_inverse">@color/car_seekbar_track_background_light
</color>
<!-- The color of the seekbar track background in SeekbarListItem. This color is assumed to be
on a light-colored background. -->
diff --git a/car/res/values/dimens.xml b/car/res/values/dimens.xml
index 2f77343..c310ec7 100644
--- a/car/res/values/dimens.xml
+++ b/car/res/values/dimens.xml
@@ -62,15 +62,20 @@
<dimen name="car_body4_size">14sp</dimen>
<dimen name="car_body5_size">18sp</dimen>
<dimen name="car_label1_size">26sp</dimen>
+ <dimen name="car_label2_size">64sp</dimen>
<dimen name="car_action1_size">26sp</dimen>
+ <dimen name="car_action2_size">26sp</dimen>
<!-- Icons and Buttons -->
<!-- Icons -->
<dimen name="car_primary_icon_size">44dp</dimen>
<dimen name="car_secondary_icon_size">24dp</dimen>
+ <dimen name="car_fab_icon_size">76dp</dimen>
+ <dimen name="car_app_icon_size">76dp</dimen>
<!-- Avatars -->
<dimen name="car_avatar_size">56dp</dimen>
+ <dimen name="car_large_avatar_size">96dp</dimen>
<!-- Minimum touch target size. -->
<dimen name="car_touch_target_size">76dp</dimen>
@@ -81,13 +86,22 @@
<dimen name="car_button_horizontal_padding">@dimen/car_padding_4</dimen>
<dimen name="car_borderless_button_horizontal_padding">0dp</dimen>
<dimen name="car_button_radius">@dimen/car_radius_1</dimen>
+ <dimen name="car_pill_button_size">56dp</dimen>
+
+ <!-- Status Bar -->
+ <dimen name="car_status_bar_height">36dp</dimen>
+ <dimen name="car_status_bar_icon_size">24dp</dimen>
+
+ <!-- Navigation Bar -->
+ <dimen name="car_navigation_bar_height">80dp</dimen>
<!-- Application Bar -->
<dimen name="car_app_bar_height">80dp</dimen>
<dimen name="car_app_bar_default_elevation">8dp</dimen>
+ <dimen name="car_application_icon_size">44dp</dimen>
<!-- Action Bar -->
- <dimen name="car_action_bar_height">128dp</dimen>
+ <dimen name="car_action_bar_height">96dp</dimen>
<dimen name="car_action_bar_buttons_space">@dimen/car_padding_4</dimen>
<dimen name="car_action_bar_button_width">128dp</dimen>
<dimen name="car_action_bar_button_height">128dp</dimen>
@@ -146,6 +160,9 @@
<!-- Text Input -->
<dimen name="car_text_input_line_height">2dp</dimen>
+ <!-- Grid Spacing -->
+ <dimen name="car_grid_spacing_minimum">32dp</dimen>
+
<!-- PagedListView Dimensions -->
<!-- Sample row height used for scroll bar calculations in the off chance that a view hasn't
been measured. It's highly unlikely that this value will actually be used for more than
@@ -164,6 +181,9 @@
cover the screen. -->
<dimen name="car_drawer_margin_end">96dp</dimen>
+ <!-- Drawer Max Width -->
+ <dimen name="car_drawer_max_width">720dp</dimen>
+
<!-- Dimensions of the back arrow in the drawer. -->
<dimen name="car_arrow_size">96dp</dimen>
<dimen name="car_arrow_thickness">3dp</dimen>
diff --git a/car/res/values/integers.xml b/car/res/values/integers.xml
index a9f6284..1acb572 100644
--- a/car/res/values/integers.xml
+++ b/car/res/values/integers.xml
@@ -28,6 +28,9 @@
<!-- Slide Up Menu -->
<integer name="car_slide_up_menu_column_number">4</integer>
+ <!-- Slide Down Menu -->
+ <integer name="car_slide_down_menu_column_number">4</integer>
+
<!-- The length limit of body text in a paged list item. String longer than this limit should be
truncated. -->
<integer name="car_list_item_text_length_limit">120</integer>
diff --git a/car/src/androidTest/java/androidx/car/widget/SeekbarListItemTest.java b/car/src/androidTest/java/androidx/car/widget/SeekbarListItemTest.java
index 207a51e..f8b8d33 100644
--- a/car/src/androidTest/java/androidx/car/widget/SeekbarListItemTest.java
+++ b/car/src/androidTest/java/androidx/car/widget/SeekbarListItemTest.java
@@ -30,6 +30,7 @@
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
import android.support.test.espresso.UiController;
import android.support.test.espresso.ViewAction;
import android.support.test.filters.SmallTest;
@@ -278,6 +279,18 @@
}
}
+ @Test
+ public void testSettingSupplementalIconWithDrawable() {
+ Drawable drawable = mActivity.getDrawable(android.R.drawable.sym_def_app_icon);
+ SeekbarListItem item = new SeekbarListItem(mActivity, 0, 0, null, null);
+ item.setSupplementalIcon(drawable, false);
+
+ setupPagedListView(Arrays.asList(item));
+
+ assertThat(getViewHolderAtPosition(0).getSupplementalIcon().getDrawable(),
+ is(equalTo(drawable)));
+ }
+
private static ViewAction clickChildViewWithId(final int id) {
return new ViewAction() {
@Override
diff --git a/car/src/androidTest/java/androidx/car/widget/TextListItemTest.java b/car/src/androidTest/java/androidx/car/widget/TextListItemTest.java
index 9a9e46d..c96b46d 100644
--- a/car/src/androidTest/java/androidx/car/widget/TextListItemTest.java
+++ b/car/src/androidTest/java/androidx/car/widget/TextListItemTest.java
@@ -212,6 +212,18 @@
}
@Test
+ public void testSetSupplementalActionWithDrawable() {
+ Drawable drawable = mActivity.getDrawable(android.R.drawable.sym_def_app_icon);
+ TextListItem item = new TextListItem(mActivity);
+ item.setSupplementalIcon(drawable, true);
+
+ setupPagedListView(Arrays.asList(item));
+
+ assertThat(getViewHolderAtPosition(0).getSupplementalIcon().getDrawable(),
+ is(equalTo(drawable)));
+ }
+
+ @Test
public void testSwitchVisibleAndCheckedState() {
TextListItem item0 = new TextListItem(mActivity);
item0.setSwitch(true, true, null);
diff --git a/car/src/main/java/androidx/car/widget/SeekbarListItem.java b/car/src/main/java/androidx/car/widget/SeekbarListItem.java
index 368e6c0..24dd58b 100644
--- a/car/src/main/java/androidx/car/widget/SeekbarListItem.java
+++ b/car/src/main/java/androidx/car/widget/SeekbarListItem.java
@@ -21,10 +21,6 @@
import android.car.drivingstate.CarUxRestrictions;
import android.content.Context;
import android.graphics.drawable.Drawable;
-import androidx.annotation.DrawableRes;
-import androidx.annotation.IdRes;
-import androidx.annotation.IntDef;
-import androidx.annotation.Nullable;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
@@ -38,6 +34,9 @@
import java.util.ArrayList;
import java.util.List;
+import androidx.annotation.DrawableRes;
+import androidx.annotation.IntDef;
+import androidx.annotation.Nullable;
import androidx.car.R;
import androidx.car.utils.CarUxRestrictionsUtils;
@@ -96,7 +95,6 @@
private final List<ViewBinder<ViewHolder>> mBinders = new ArrayList<>();
@PrimaryActionType private int mPrimaryActionType = PRIMARY_ACTION_TYPE_NO_ICON;
- private int mPrimaryActionIconResId;
private Drawable mPrimaryActionIconDrawable;
private String mText;
@@ -106,7 +104,7 @@
private SeekBar.OnSeekBarChangeListener mOnSeekBarChangeListener;
@SupplementalActionType private int mSupplementalActionType = SUPPLEMENTAL_ACTION_NO_ACTION;
- private int mSupplementalIconResId;
+ private Drawable mSupplementalIconDrawable;
private View.OnClickListener mSupplementalIconOnClickListener;
private boolean mShowSupplementalIconDivider;
@@ -250,12 +248,7 @@
case PRIMARY_ACTION_TYPE_SMALL_ICON:
mBinders.add(vh -> {
vh.getPrimaryIcon().setVisibility(View.VISIBLE);
-
- if (mPrimaryActionIconDrawable != null) {
- vh.getPrimaryIcon().setImageDrawable(mPrimaryActionIconDrawable);
- } else if (mPrimaryActionIconResId != 0) {
- vh.getPrimaryIcon().setImageResource(mPrimaryActionIconResId);
- }
+ vh.getPrimaryIcon().setImageDrawable(mPrimaryActionIconDrawable);
});
break;
default:
@@ -405,7 +398,8 @@
vh.getSupplementalIconDivider().setVisibility(View.VISIBLE);
}
- vh.getSupplementalIcon().setImageResource(mSupplementalIconResId);
+ vh.getSupplementalIcon().setImageDrawable(mSupplementalIconDrawable);
+
vh.getSupplementalIcon().setOnClickListener(
mSupplementalIconOnClickListener);
vh.getSupplementalIcon().setClickable(
@@ -423,7 +417,7 @@
* @param iconResId the resource identifier of the drawable.
*/
public void setPrimaryActionIcon(@DrawableRes int iconResId) {
- setPrimaryActionIcon(null, iconResId);
+ setPrimaryActionIcon(mContext.getDrawable(iconResId));
}
/**
@@ -432,15 +426,8 @@
* @param drawable the Drawable to set, or null to clear the content.
*/
public void setPrimaryActionIcon(Drawable drawable) {
- setPrimaryActionIcon(drawable, 0);
- }
-
- private void setPrimaryActionIcon(Drawable drawable, @DrawableRes int iconResId) {
mPrimaryActionType = PRIMARY_ACTION_TYPE_SMALL_ICON;
-
mPrimaryActionIconDrawable = drawable;
- mPrimaryActionIconResId = iconResId;
-
markDirty();
}
@@ -458,18 +445,34 @@
/**
* Sets {@code Supplemental Action} to be represented by an {@code Supplemental Icon}.
*/
- public void setSupplementalIcon(int iconResId, boolean showSupplementalIconDivider) {
- setSupplementalIcon(iconResId, showSupplementalIconDivider, null);
+ public void setSupplementalIcon(@DrawableRes int iconResId,
+ boolean showSupplementalIconDivider) {
+ setSupplementalIcon(mContext.getDrawable(iconResId), showSupplementalIconDivider, null);
}
/**
* Sets {@code Supplemental Action} to be represented by an {@code Supplemental Icon}.
*/
- public void setSupplementalIcon(@IdRes int iconResId,
- boolean showSupplementalIconDivider, @Nullable View.OnClickListener listener) {
+ public void setSupplementalIcon(@DrawableRes int iconResId, boolean showSupplementalIconDivider,
+ @Nullable View.OnClickListener listener) {
+ setSupplementalIcon(mContext.getDrawable(iconResId), showSupplementalIconDivider, listener);
+ }
+
+ /**
+ * Sets {@code Supplemental Action} to be represented by an {@code Supplemental Icon}.
+ */
+ public void setSupplementalIcon(Drawable drawable, boolean showSupplementalIconDivider) {
+ setSupplementalIcon(drawable, showSupplementalIconDivider, null);
+ }
+
+ /**
+ * Sets {@code Supplemental Action} to be represented by an {@code Supplemental Icon}.
+ */
+ public void setSupplementalIcon(Drawable drawable, boolean showSupplementalIconDivider,
+ @Nullable View.OnClickListener listener) {
mSupplementalActionType = SUPPLEMENTAL_ACTION_SUPPLEMENTAL_ICON;
- mSupplementalIconResId = iconResId;
+ mSupplementalIconDrawable = drawable;
mShowSupplementalIconDivider = showSupplementalIconDivider;
mSupplementalIconOnClickListener = listener;
diff --git a/car/src/main/java/androidx/car/widget/TextListItem.java b/car/src/main/java/androidx/car/widget/TextListItem.java
index ce64a2d..3681d3e 100644
--- a/car/src/main/java/androidx/car/widget/TextListItem.java
+++ b/car/src/main/java/androidx/car/widget/TextListItem.java
@@ -109,7 +109,6 @@
private View.OnClickListener mOnClickListener;
@PrimaryActionType private int mPrimaryActionType = PRIMARY_ACTION_TYPE_NO_ICON;
- private int mPrimaryActionIconResId;
private Drawable mPrimaryActionIconDrawable;
private String mTitle;
@@ -117,7 +116,7 @@
private boolean mIsBodyPrimary;
@SupplementalActionType private int mSupplementalActionType = SUPPLEMENTAL_ACTION_NO_ACTION;
- private int mSupplementalIconResId;
+ private Drawable mSupplementalIconDrawable;
private View.OnClickListener mSupplementalIconOnClickListener;
private boolean mShowSupplementalIconDivider;
@@ -257,11 +256,7 @@
mBinders.add(vh -> {
vh.getPrimaryIcon().setVisibility(View.VISIBLE);
- if (mPrimaryActionIconDrawable != null) {
- vh.getPrimaryIcon().setImageDrawable(mPrimaryActionIconDrawable);
- } else if (mPrimaryActionIconResId != 0) {
- vh.getPrimaryIcon().setImageResource(mPrimaryActionIconResId);
- }
+ vh.getPrimaryIcon().setImageDrawable(mPrimaryActionIconDrawable);
});
break;
case PRIMARY_ACTION_TYPE_EMPTY_ICON:
@@ -544,7 +539,7 @@
vh.getSupplementalIconDivider().setVisibility(View.VISIBLE);
}
- vh.getSupplementalIcon().setImageResource(mSupplementalIconResId);
+ vh.getSupplementalIcon().setImageDrawable(mSupplementalIconDrawable);
vh.getSupplementalIcon().setOnClickListener(
mSupplementalIconOnClickListener);
vh.getSupplementalIcon().setClickable(
@@ -606,7 +601,7 @@
* @param useLargeIcon the size of primary icon. Large Icon is a square as tall as an item.
*/
public void setPrimaryActionIcon(@DrawableRes int iconResId, boolean useLargeIcon) {
- setPrimaryActionIcon(null, iconResId, useLargeIcon);
+ setPrimaryActionIcon(mContext.getDrawable(iconResId), useLargeIcon);
}
/**
@@ -616,15 +611,9 @@
* @param useLargeIcon the size of primary icon. Large Icon is a square as tall as an item.
*/
public void setPrimaryActionIcon(Drawable drawable, boolean useLargeIcon) {
- setPrimaryActionIcon(drawable, 0, useLargeIcon);
- }
-
- private void setPrimaryActionIcon(Drawable drawable, @DrawableRes int iconResId,
- boolean useLargeIcon) {
mPrimaryActionType = useLargeIcon
? PRIMARY_ACTION_TYPE_LARGE_ICON
: PRIMARY_ACTION_TYPE_SMALL_ICON;
- mPrimaryActionIconResId = iconResId;
mPrimaryActionIconDrawable = drawable;
markDirty();
@@ -696,7 +685,18 @@
* {@code Supplemental Icon}.
*/
public void setSupplementalIcon(int iconResId, boolean showDivider) {
- setSupplementalIcon(iconResId, showDivider, null);
+ setSupplementalIcon(mContext.getDrawable(iconResId), showDivider, null);
+ }
+
+ /**
+ * Sets {@code Supplemental Action} to be represented by an {@code Supplemental Icon}.
+ *
+ * @param drawable the Drawable to set, or null to clear the content.
+ * @param showDivider whether to display a vertical bar that separates {@code text} and
+ * {@code Supplemental Icon}.
+ */
+ public void setSupplementalIcon(Drawable drawable, boolean showDivider) {
+ setSupplementalIcon(drawable, showDivider, null);
}
/**
@@ -709,9 +709,22 @@
*/
public void setSupplementalIcon(int iconResId, boolean showDivider,
View.OnClickListener listener) {
+ setSupplementalIcon(mContext.getDrawable(iconResId), showDivider, listener);
+ }
+
+ /**
+ * Sets {@code Supplemental Action} to be represented by an {@code Supplemental Icon}.
+ *
+ * @param drawable the Drawable to set, or null to clear the content.
+ * @param showDivider whether to display a vertical bar that separates {@code text} and
+ * {@code Supplemental Icon}.
+ * @param listener the callback that will run when icon is clicked.
+ */
+ public void setSupplementalIcon(Drawable drawable, boolean showDivider,
+ View.OnClickListener listener) {
mSupplementalActionType = SUPPLEMENTAL_ACTION_SUPPLEMENTAL_ICON;
- mSupplementalIconResId = iconResId;
+ mSupplementalIconDrawable = drawable;
mSupplementalIconOnClickListener = listener;
mShowSupplementalIconDivider = showDivider;
markDirty();
diff --git a/cardview/build.gradle b/cardview/build.gradle
index d583284..c950dac 100644
--- a/cardview/build.gradle
+++ b/cardview/build.gradle
@@ -22,4 +22,5 @@
mavenGroup = LibraryGroups.CARDVIEW
inceptionYear = "2011"
description = "Android Support CardView v7"
+ failOnDeprecationWarnings = false
}
diff --git a/compat/api/current.txt b/compat/api/current.txt
index 1ceedbe..fc0629d 100644
--- a/compat/api/current.txt
+++ b/compat/api/current.txt
@@ -576,7 +576,7 @@
public class Person {
method public static androidx.core.app.Person fromBundle(android.os.Bundle);
- method public android.graphics.Bitmap getIcon();
+ method public androidx.core.graphics.drawable.IconCompat getIcon();
method public java.lang.String getKey();
method public java.lang.CharSequence getName();
method public java.lang.String getUri();
@@ -590,7 +590,7 @@
ctor public Person.Builder();
method public androidx.core.app.Person build();
method public androidx.core.app.Person.Builder setBot(boolean);
- method public androidx.core.app.Person.Builder setIcon(android.graphics.Bitmap);
+ method public androidx.core.app.Person.Builder setIcon(androidx.core.graphics.drawable.IconCompat);
method public androidx.core.app.Person.Builder setImportant(boolean);
method public androidx.core.app.Person.Builder setKey(java.lang.String);
method public androidx.core.app.Person.Builder setName(java.lang.CharSequence);
@@ -809,6 +809,11 @@
method public static long getLongVersionCode(android.content.pm.PackageInfo);
}
+ public final class PermissionInfoCompat {
+ method public static int getProtection(android.content.pm.PermissionInfo);
+ method public static int getProtectionFlags(android.content.pm.PermissionInfo);
+ }
+
public class ShortcutInfoCompat {
method public android.content.ComponentName getActivity();
method public java.lang.CharSequence getDisabledMessage();
diff --git a/compat/build.gradle b/compat/build.gradle
index 940819b..e4a719a 100644
--- a/compat/build.gradle
+++ b/compat/build.gradle
@@ -37,4 +37,6 @@
mavenGroup = LibraryGroups.CORE
inceptionYear = "2015"
description = "The Support Library is a static library that you can add to your Android application in order to use APIs that are either not available for older platform versions or utility APIs that aren\'t a part of the framework APIs. Compatible on devices running API 14 or later."
+ failOnUncheckedWarnings = false
+ failOnDeprecationWarnings = false
}
diff --git a/compat/src/androidTest/java/androidx/core/app/PersonTest.java b/compat/src/androidTest/java/androidx/core/app/PersonTest.java
index 20b2090..12f6117 100644
--- a/compat/src/androidTest/java/androidx/core/app/PersonTest.java
+++ b/compat/src/androidTest/java/androidx/core/app/PersonTest.java
@@ -17,14 +17,16 @@
package androidx.core.app;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
import android.graphics.Bitmap;
import android.os.Bundle;
-import android.support.test.filters.SdkSuppress;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
+import androidx.core.graphics.drawable.IconCompat;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -32,14 +34,14 @@
@RunWith(AndroidJUnit4.class)
public class PersonTest {
private static final CharSequence TEST_NAME = "Example Name";
- private static final Bitmap TEST_ICON = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
+ private static final IconCompat TEST_ICON =
+ IconCompat.createWithBitmap(Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888));
private static final String TEST_URI = "mailto:example@example.com";
private static final String TEST_KEY = "example-key";
private static final boolean TEST_IS_BOT = true;
private static final boolean TEST_IS_IMPORTANT = true;
@Test
- @SdkSuppress(minSdkVersion = 12)
public void bundle() {
Person person = new Person.Builder()
.setImportant(TEST_IS_IMPORTANT)
@@ -58,13 +60,25 @@
assertEquals(TEST_KEY, result.getKey());
assertEquals(TEST_IS_BOT, result.isBot());
assertEquals(TEST_IS_IMPORTANT, result.isImportant());
-
- // Requires SDK >= 12
- assertTrue(TEST_ICON.sameAs(result.getIcon()));
+ assertEquals(TEST_ICON.toBundle().toString(), result.getIcon().toBundle().toString());
}
@Test
- @SdkSuppress(minSdkVersion = 12)
+ public void bundle_defaultValues() {
+ Person person = new Person.Builder().build();
+
+ Bundle personBundle = person.toBundle();
+ Person result = Person.fromBundle(personBundle);
+
+ assertNull(result.getIcon());
+ assertNull(result.getKey());
+ assertNull(result.getName());
+ assertNull(result.getUri());
+ assertFalse(result.isImportant());
+ assertFalse(result.isBot());
+ }
+
+ @Test
public void toBuilder() {
Person person = new Person.Builder()
.setImportant(TEST_IS_IMPORTANT)
@@ -81,9 +95,7 @@
assertEquals(TEST_KEY, result.getKey());
assertEquals(TEST_IS_BOT, result.isBot());
assertEquals(TEST_IS_IMPORTANT, result.isImportant());
-
- // Requires SDK >= 12
- assertTrue(TEST_ICON.sameAs(result.getIcon()));
+ assertEquals(TEST_ICON.toBundle().toString(), result.getIcon().toBundle().toString());
}
@Test
diff --git a/compat/src/androidTest/java/androidx/core/content/pm/PermissionInfoCompatTest.java b/compat/src/androidTest/java/androidx/core/content/pm/PermissionInfoCompatTest.java
new file mode 100644
index 0000000..79613be
--- /dev/null
+++ b/compat/src/androidTest/java/androidx/core/content/pm/PermissionInfoCompatTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018 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 androidx.core.content.pm;
+
+import android.content.pm.PermissionInfo;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class PermissionInfoCompatTest {
+ @Test
+ public void testGetProtectionAndFlags() {
+ PermissionInfo pi = new PermissionInfo();
+
+ pi.protectionLevel = PermissionInfo.PROTECTION_DANGEROUS
+ | PermissionInfo.PROTECTION_FLAG_PRIVILEGED;
+
+ Assert.assertEquals(PermissionInfo.PROTECTION_DANGEROUS,
+ PermissionInfoCompat.getProtection(pi));
+
+ Assert.assertEquals(PermissionInfo.PROTECTION_FLAG_PRIVILEGED,
+ PermissionInfoCompat.getProtectionFlags(pi));
+
+ pi.protectionLevel = 0xf | 0xfff0;
+ Assert.assertEquals(0xf, PermissionInfoCompat.getProtection(pi));
+ Assert.assertEquals(0xfff0, PermissionInfoCompat.getProtectionFlags(pi));
+ }
+}
diff --git a/compat/src/main/java/androidx/core/app/Person.java b/compat/src/main/java/androidx/core/app/Person.java
index 3bda510..e79076e 100644
--- a/compat/src/main/java/androidx/core/app/Person.java
+++ b/compat/src/main/java/androidx/core/app/Person.java
@@ -16,11 +16,11 @@
package androidx.core.app;
-import android.graphics.Bitmap;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.core.graphics.drawable.IconCompat;
/**
* Provides an immutable reference to an entity that appears repeatedly on different surfaces of the
@@ -39,9 +39,10 @@
* created from a {@link Person} using {@link #toBundle()}.
*/
public static Person fromBundle(Bundle bundle) {
+ Bundle iconBundle = bundle.getBundle(ICON_KEY);
return new Builder()
.setName(bundle.getCharSequence(NAME_KEY))
- .setIcon((Bitmap) bundle.getParcelable(ICON_KEY))
+ .setIcon(iconBundle != null ? IconCompat.createFromBundle(iconBundle) : null)
.setUri(bundle.getString(URI_KEY))
.setKey(bundle.getString(KEY_KEY))
.setBot(bundle.getBoolean(IS_BOT_KEY))
@@ -50,7 +51,7 @@
}
@Nullable private CharSequence mName;
- @Nullable private Bitmap mIcon;
+ @Nullable private IconCompat mIcon;
@Nullable private String mUri;
@Nullable private String mKey;
private boolean mIsBot;
@@ -72,7 +73,7 @@
public Bundle toBundle() {
Bundle result = new Bundle();
result.putCharSequence(NAME_KEY, mName);
- result.putParcelable(ICON_KEY, mIcon);
+ result.putBundle(ICON_KEY, mIcon != null ? mIcon.toBundle() : null);
result.putString(URI_KEY, mUri);
result.putString(KEY_KEY, mKey);
result.putBoolean(IS_BOT_KEY, mIsBot);
@@ -96,7 +97,7 @@
/** Returns the icon for this {@link Person} or {@code null} if no icon was provided. */
@Nullable
- public Bitmap getIcon() {
+ public IconCompat getIcon() {
return mIcon;
}
@@ -146,7 +147,7 @@
/** Builder for the immutable {@link Person} class. */
public static class Builder {
@Nullable private CharSequence mName;
- @Nullable private Bitmap mIcon;
+ @Nullable private IconCompat mIcon;
@Nullable private String mUri;
@Nullable private String mKey;
private boolean mIsBot;
@@ -181,7 +182,7 @@
* {@link #setUri(String)}.
*/
@NonNull
- public Builder setIcon(@Nullable Bitmap icon) {
+ public Builder setIcon(@Nullable IconCompat icon) {
mIcon = icon;
return this;
}
diff --git a/compat/src/main/java/androidx/core/content/pm/PermissionInfoCompat.java b/compat/src/main/java/androidx/core/content/pm/PermissionInfoCompat.java
new file mode 100644
index 0000000..df095a6
--- /dev/null
+++ b/compat/src/main/java/androidx/core/content/pm/PermissionInfoCompat.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2018 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 androidx.core.content.pm;
+
+import android.annotation.SuppressLint;
+import android.content.pm.PermissionInfo;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+import androidx.core.os.BuildCompat;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Helper for accessing features in {@link PermissionInfo}.
+ */
+public final class PermissionInfoCompat {
+ private PermissionInfoCompat() {
+ }
+
+ /** @hide */
+ @IntDef(flag = false, value = {
+ PermissionInfo.PROTECTION_NORMAL,
+ PermissionInfo.PROTECTION_DANGEROUS,
+ PermissionInfo.PROTECTION_SIGNATURE,
+ PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM,
+ })
+ @RestrictTo(RestrictTo.Scope.LIBRARY)
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Protection {}
+
+ /** @hide */
+ @SuppressLint("UniqueConstants") // because _SYSTEM and _PRIVILEGED are aliases.
+ @IntDef(flag = true, value = {
+ PermissionInfo.PROTECTION_FLAG_PRIVILEGED,
+ PermissionInfo.PROTECTION_FLAG_SYSTEM,
+ PermissionInfo.PROTECTION_FLAG_DEVELOPMENT,
+ PermissionInfo.PROTECTION_FLAG_APPOP,
+ PermissionInfo.PROTECTION_FLAG_PRE23,
+ PermissionInfo.PROTECTION_FLAG_INSTALLER,
+ PermissionInfo.PROTECTION_FLAG_VERIFIER,
+ PermissionInfo.PROTECTION_FLAG_PREINSTALLED,
+ PermissionInfo.PROTECTION_FLAG_SETUP,
+ PermissionInfo.PROTECTION_FLAG_INSTANT,
+ PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY,
+ })
+ @RestrictTo(RestrictTo.Scope.LIBRARY)
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ProtectionFlags {}
+
+ /**
+ * Return the base permission type of a {@link PermissionInfo}.
+ */
+ @SuppressLint("WrongConstant") // for "PermissionInfo.PROTECTION_MASK_BASE"
+ @Protection
+ public static int getProtection(@NonNull PermissionInfo permissionInfo) {
+ if (BuildCompat.isAtLeastP()) {
+ return permissionInfo.getProtection();
+ } else {
+ return permissionInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
+ }
+ }
+
+ /**
+ * Return the additional protection flags of a {@link PermissionInfo}.
+ */
+ @SuppressLint("WrongConstant") // for "~PermissionInfo.PROTECTION_MASK_BASE"
+ @ProtectionFlags
+ public static int getProtectionFlags(@NonNull PermissionInfo permissionInfo) {
+ if (BuildCompat.isAtLeastP()) {
+ return permissionInfo.getProtectionFlags();
+ } else {
+ return permissionInfo.protectionLevel & ~PermissionInfo.PROTECTION_MASK_BASE;
+ }
+ }
+}
diff --git a/content/build.gradle b/content/build.gradle
index 25b01e5..d5f8b80 100644
--- a/content/build.gradle
+++ b/content/build.gradle
@@ -38,4 +38,5 @@
mavenGroup = LibraryGroups.CONTENTPAGING
inceptionYear = "2017"
description = "Library providing support for paging across content exposed via a ContentProvider. Use of this library allows a client to avoid expensive interprocess \"cursor window swaps\" on the UI thread."
+ failOnDeprecationWarnings = false
}
diff --git a/coordinatorlayout/build.gradle b/coordinatorlayout/build.gradle
index 8e72580..4775f67 100644
--- a/coordinatorlayout/build.gradle
+++ b/coordinatorlayout/build.gradle
@@ -39,4 +39,6 @@
mavenGroup = LibraryGroups.COORDINATORLAYOUT
inceptionYear = "2011"
description = "The Support Library is a static library that you can add to your Android application in order to use APIs that are either not available for older platform versions or utility APIs that aren't a part of the framework APIs. Compatible on devices running API 14 or later."
+ failOnUncheckedWarnings = false
+ failOnDeprecationWarnings = false
}
diff --git a/cursoradapter/build.gradle b/cursoradapter/build.gradle
index ce80655..2493a2b 100644
--- a/cursoradapter/build.gradle
+++ b/cursoradapter/build.gradle
@@ -16,4 +16,5 @@
mavenGroup = LibraryGroups.CURSORADAPTER
inceptionYear = "2018"
description = "The Support Library is a static library that you can add to your Android application in order to use APIs that are either not available for older platform versions or utility APIs that aren't a part of the framework APIs. Compatible on devices running API 14 or later."
+ failOnDeprecationWarnings = false
}
diff --git a/customview/build.gradle b/customview/build.gradle
index 37cfc2f..f2ebd43 100644
--- a/customview/build.gradle
+++ b/customview/build.gradle
@@ -22,4 +22,5 @@
mavenGroup = LibraryGroups.CUSTOMVIEW
inceptionYear = "2018"
description = "The Support Library is a static library that you can add to your Android application in order to use APIs that are either not available for older platform versions or utility APIs that aren't a part of the framework APIs. Compatible on devices running API 14 or later."
+ failOnDeprecationWarnings = false
}
diff --git a/dynamic-animation/build.gradle b/dynamic-animation/build.gradle
index 637abb4..6da13e0 100644
--- a/dynamic-animation/build.gradle
+++ b/dynamic-animation/build.gradle
@@ -24,4 +24,5 @@
mavenGroup = LibraryGroups.DYNAMICANIMATION
inceptionYear = "2017"
description = "Physics-based animation in support library, where the animations are driven by physics force. You can use this Animation library to create smooth and realistic animations."
+ failOnUncheckedWarnings = false
}
\ No newline at end of file
diff --git a/fragment/build.gradle b/fragment/build.gradle
index 5f8954f..7faa903 100644
--- a/fragment/build.gradle
+++ b/fragment/build.gradle
@@ -30,4 +30,6 @@
mavenGroup = LibraryGroups.FRAGMENT
inceptionYear = "2011"
description = "The Support Library is a static library that you can add to your Android application in order to use APIs that are either not available for older platform versions or utility APIs that aren\'t a part of the framework APIs. Compatible on devices running API 14 or later."
+ failOnUncheckedWarnings = false
+ failOnDeprecationWarnings = false
}
diff --git a/graphics/drawable/static/build.gradle b/graphics/drawable/static/build.gradle
index 19a0366..423cb22 100644
--- a/graphics/drawable/static/build.gradle
+++ b/graphics/drawable/static/build.gradle
@@ -31,4 +31,5 @@
mavenGroup = LibraryGroups.VECTORDRAWABLE
inceptionYear = "2015"
description = "Android Support VectorDrawable"
+ failOnDeprecationWarnings = false
}
\ No newline at end of file
diff --git a/gridlayout/build.gradle b/gridlayout/build.gradle
index fb4dd10..930e191 100644
--- a/gridlayout/build.gradle
+++ b/gridlayout/build.gradle
@@ -21,4 +21,5 @@
mavenGroup = LibraryGroups.GRIDLAYOUT
inceptionYear = "2013"
description = "Android Support Grid Layout"
+ failOnDeprecationWarnings = false
}
diff --git a/jetifier/jetifier/processor/src/main/kotlin/com/android/tools/build/jetifier/processor/transform/bytecode/CoreRemapperImpl.kt b/jetifier/jetifier/processor/src/main/kotlin/com/android/tools/build/jetifier/processor/transform/bytecode/CoreRemapperImpl.kt
index aa769dd..37a22da 100644
--- a/jetifier/jetifier/processor/src/main/kotlin/com/android/tools/build/jetifier/processor/transform/bytecode/CoreRemapperImpl.kt
+++ b/jetifier/jetifier/processor/src/main/kotlin/com/android/tools/build/jetifier/processor/transform/bytecode/CoreRemapperImpl.kt
@@ -68,11 +68,11 @@
return value
}
- val result = context.config.typesMap.mapType(type)
- if (result != null) {
- changesDone = changesDone || result != type
- Log.i(TAG, "Map string: '%s' -> '%s'", type, result)
- return result.toDotNotation()
+ val mappedType = context.config.typesMap.mapType(type)
+ if (mappedType != null) {
+ changesDone = changesDone || mappedType != type
+ Log.i(TAG, "Map string: '%s' -> '%s'", type, mappedType)
+ return mappedType.toDotNotation()
}
// We might be working with an internal type or field reference, e.g.
@@ -88,10 +88,10 @@
// Try rewrite rules
if (context.useFallbackIfTypeIsMissing) {
- val result = context.config.rulesMap.rewriteType(type)
- if (result != null) {
- Log.i(TAG, "Map string: '%s' -> '%s' via fallback", value, result)
- return result.toDotNotation()
+ val rewrittenType = context.config.rulesMap.rewriteType(type)
+ if (rewrittenType != null) {
+ Log.i(TAG, "Map string: '%s' -> '%s' via fallback", value, rewrittenType)
+ return rewrittenType.toDotNotation()
}
}
@@ -119,4 +119,4 @@
return path
}
-}
\ No newline at end of file
+}
diff --git a/jetifier/jetifier/source-transformer/rewritePackageNames.py b/jetifier/jetifier/source-transformer/rewritePackageNames.py
index 5cfea14..43dba21 100755
--- a/jetifier/jetifier/source-transformer/rewritePackageNames.py
+++ b/jetifier/jetifier/source-transformer/rewritePackageNames.py
@@ -11,6 +11,17 @@
import os.path
import subprocess
+HARDCODED_RULES_REVERSE = [
+ "s|androidx.core.media.MediaBrowserCompat|android.support.v4.media.MediaBrowserCompat|g\n",
+ "s|androidx.core.media.MediaDescriptionCompat|android.support.v4.media.MediaDescriptionCompat|g\n",
+ "s|androidx.core.media.MediaMetadataCompat|android.support.v4.media.MediaMetadataCompat|g\n",
+ "s|androidx.core.media.RatingCompat|android.support.v4.media.RatingCompat|g\n",
+ "s|androidx.core.media.session.MediaControllerCompat|android.support.v4.media.session.MediaControllerCompat|g\n",
+ "s|androidx.core.media.session.MediaSessionCompat|android.support.v4.media.session.MediaSessionCompat|g\n",
+ "s|androidx.core.media.session.ParcelableVolumeInfo|android.support.v4.media.session.ParcelableVolumeInfo|g\n",
+ "s|androidx.core.media.session.PlaybackStateCompat|android.support.v4.media.session.PlaybackStateCompat|g\n",
+]
+
class StringBuilder(object):
def __init__(self, item=None):
self.items = []
@@ -76,7 +87,7 @@
finderTextBuilder.add(" ").add(sourceRoot)
for exclusion in executionConfig.excludeDirs:
finderTextBuilder.add(" -name ").add(exclusion).add(" -prune -o")
- finderTextBuilder.add(" -iregex '.*\.java\|.*\.xml' -print")
+ finderTextBuilder.add(" -iregex '.*\.java\|.*\.xml\|.*\.cfg\|.*\.flags' -print")
# create command to rewrite one source
print("Building sed instructions")
@@ -84,6 +95,8 @@
rewriteRules = executionConfig.jetifierConfig.getTypesMap()
for rule in rewriteRules:
rewriterTextBuilder.add("s|").add(rule.fromName).add("|").add(rule.toName).add("|g\n")
+ for rule in HARDCODED_RULES_REVERSE:
+ rewriterTextBuilder.add(rule)
scriptPath = "/tmp/jetifier-sed-script.txt"
print("Writing " + scriptPath)
with open(scriptPath, 'w') as scriptFile:
diff --git a/leanback-preference/build.gradle b/leanback-preference/build.gradle
index a6e0d27..4f49bef 100644
--- a/leanback-preference/build.gradle
+++ b/leanback-preference/build.gradle
@@ -30,4 +30,5 @@
inceptionYear = "2015"
description = "Android Support Leanback Preference v17"
minSdkVersion = 17
+ failOnDeprecationWarnings = false
}
\ No newline at end of file
diff --git a/leanback/build.gradle b/leanback/build.gradle
index 56b7fc5..a1e468b 100644
--- a/leanback/build.gradle
+++ b/leanback/build.gradle
@@ -37,4 +37,6 @@
inceptionYear = "2014"
description = "Android Support Leanback v17"
minSdkVersion = 17
+ failOnUncheckedWarnings = false
+ failOnDeprecationWarnings = false
}
diff --git a/legacy/v13/build.gradle b/legacy/v13/build.gradle
index d8ef8f7..c881632 100644
--- a/legacy/v13/build.gradle
+++ b/legacy/v13/build.gradle
@@ -16,4 +16,5 @@
mavenGroup = LibraryGroups.LEGACY
inceptionYear = "2011"
description = "The Support Library is a static library that you can add to your Android application in order to use APIs that are either not available for older platform versions or utility APIs that aren't a part of the framework APIs. Compatible on devices running API 14 or later."
+ failOnDeprecationWarnings = false
}
diff --git a/lifecycle/extensions/build.gradle b/lifecycle/extensions/build.gradle
index a2be25d..14a974c 100644
--- a/lifecycle/extensions/build.gradle
+++ b/lifecycle/extensions/build.gradle
@@ -55,4 +55,5 @@
inceptionYear = "2017"
description = "Android Lifecycle Extensions"
url = SupportLibraryExtension.ARCHITECTURE_URL
+ failOnDeprecationWarnings = false
}
diff --git a/lifecycle/livedata-core/build.gradle b/lifecycle/livedata-core/build.gradle
index 76f6c83..e9e1cfd 100644
--- a/lifecycle/livedata-core/build.gradle
+++ b/lifecycle/livedata-core/build.gradle
@@ -42,4 +42,5 @@
inceptionYear = "2017"
description = "Android Lifecycle LiveData Core"
url = SupportLibraryExtension.ARCHITECTURE_URL
+ failOnUncheckedWarnings = false
}
diff --git a/lifecycle/runtime/build.gradle b/lifecycle/runtime/build.gradle
index baa2b32..40b250c 100644
--- a/lifecycle/runtime/build.gradle
+++ b/lifecycle/runtime/build.gradle
@@ -34,4 +34,5 @@
inceptionYear '2017'
description "Android Lifecycle Runtime"
url SupportLibraryExtension.ARCHITECTURE_URL
+ failOnDeprecationWarnings = false
}
\ No newline at end of file
diff --git a/lifecycle/viewmodel/build.gradle b/lifecycle/viewmodel/build.gradle
index 1494733..cc71b39 100644
--- a/lifecycle/viewmodel/build.gradle
+++ b/lifecycle/viewmodel/build.gradle
@@ -44,4 +44,5 @@
inceptionYear = "2017"
description = "Android Lifecycle ViewModel"
url = SupportLibraryExtension.ARCHITECTURE_URL
+ failOnUncheckedWarnings = false
}
\ No newline at end of file
diff --git a/loader/build.gradle b/loader/build.gradle
index 8c99ea5..9a34ff2 100644
--- a/loader/build.gradle
+++ b/loader/build.gradle
@@ -25,4 +25,5 @@
mavenGroup = LibraryGroups.LOADER
inceptionYear = "2011"
description = "The Support Library is a static library that you can add to your Android application in order to use APIs that are either not available for older platform versions or utility APIs that aren\'t a part of the framework APIs. Compatible on devices running API 14 or later."
+ failOnUncheckedWarnings = false
}
diff --git a/media/build.gradle b/media/build.gradle
index eda587d..af0928b 100644
--- a/media/build.gradle
+++ b/media/build.gradle
@@ -41,4 +41,6 @@
mavenGroup = LibraryGroups.MEDIA
inceptionYear = "2011"
description = "The Support Library is a static library that you can add to your Android application in order to use APIs that are either not available for older platform versions or utility APIs that aren't a part of the framework APIs. Compatible on devices running API 14 or later."
+ failOnUncheckedWarnings = false
+ failOnDeprecationWarnings = false
}
diff --git a/media/version-compat-tests/lib/build.gradle b/media/version-compat-tests/lib/build.gradle
index df9e75c..f9dfeac 100644
--- a/media/version-compat-tests/lib/build.gradle
+++ b/media/version-compat-tests/lib/build.gradle
@@ -23,3 +23,7 @@
dependencies {
implementation(JUNIT)
}
+
+supportLibrary {
+ failOnUncheckedWarnings = false
+}
\ No newline at end of file
diff --git a/mediarouter/build.gradle b/mediarouter/build.gradle
index a2463a4..2044242 100644
--- a/mediarouter/build.gradle
+++ b/mediarouter/build.gradle
@@ -34,4 +34,6 @@
mavenGroup = LibraryGroups.MEDIAROUTER
inceptionYear = "2013"
description = "Android MediaRouter Support Library"
+ failOnUncheckedWarnings = false
+ failOnDeprecationWarnings = false
}
diff --git a/paging/common/api/current.txt b/paging/common/api/current.txt
new file mode 100644
index 0000000..d449e90
--- /dev/null
+++ b/paging/common/api/current.txt
@@ -0,0 +1,180 @@
+package androidx.paging {
+
+ public abstract class DataSource<Key, Value> {
+ method public void addInvalidatedCallback(androidx.paging.DataSource.InvalidatedCallback);
+ method public void invalidate();
+ method public boolean isInvalid();
+ method public abstract <ToValue> androidx.paging.DataSource<Key, ToValue> map(androidx.arch.core.util.Function<Value, ToValue>);
+ method public abstract <ToValue> androidx.paging.DataSource<Key, ToValue> mapByPage(androidx.arch.core.util.Function<java.util.List<Value>, java.util.List<ToValue>>);
+ method public void removeInvalidatedCallback(androidx.paging.DataSource.InvalidatedCallback);
+ }
+
+ public static abstract class DataSource.Factory<Key, Value> {
+ ctor public DataSource.Factory();
+ method public abstract androidx.paging.DataSource<Key, Value> create();
+ method public <ToValue> androidx.paging.DataSource.Factory<Key, ToValue> map(androidx.arch.core.util.Function<Value, ToValue>);
+ method public <ToValue> androidx.paging.DataSource.Factory<Key, ToValue> mapByPage(androidx.arch.core.util.Function<java.util.List<Value>, java.util.List<ToValue>>);
+ }
+
+ public static abstract interface DataSource.InvalidatedCallback {
+ method public abstract void onInvalidated();
+ }
+
+ public abstract class ItemKeyedDataSource<Key, Value> extends androidx.paging.DataSource {
+ ctor public ItemKeyedDataSource();
+ method public abstract Key getKey(Value);
+ method public abstract void loadAfter(androidx.paging.ItemKeyedDataSource.LoadParams<Key>, androidx.paging.ItemKeyedDataSource.LoadCallback<Value>);
+ method public abstract void loadBefore(androidx.paging.ItemKeyedDataSource.LoadParams<Key>, androidx.paging.ItemKeyedDataSource.LoadCallback<Value>);
+ method public abstract void loadInitial(androidx.paging.ItemKeyedDataSource.LoadInitialParams<Key>, androidx.paging.ItemKeyedDataSource.LoadInitialCallback<Value>);
+ method public final <ToValue> androidx.paging.ItemKeyedDataSource<Key, ToValue> map(androidx.arch.core.util.Function<Value, ToValue>);
+ method public final <ToValue> androidx.paging.ItemKeyedDataSource<Key, ToValue> mapByPage(androidx.arch.core.util.Function<java.util.List<Value>, java.util.List<ToValue>>);
+ }
+
+ public static abstract class ItemKeyedDataSource.LoadCallback<Value> {
+ ctor public ItemKeyedDataSource.LoadCallback();
+ method public abstract void onResult(java.util.List<Value>);
+ }
+
+ public static abstract class ItemKeyedDataSource.LoadInitialCallback<Value> extends androidx.paging.ItemKeyedDataSource.LoadCallback {
+ ctor public ItemKeyedDataSource.LoadInitialCallback();
+ method public abstract void onResult(java.util.List<Value>, int, int);
+ }
+
+ public static class ItemKeyedDataSource.LoadInitialParams<Key> {
+ ctor public ItemKeyedDataSource.LoadInitialParams(Key, int, boolean);
+ field public final boolean placeholdersEnabled;
+ field public final Key requestedInitialKey;
+ field public final int requestedLoadSize;
+ }
+
+ public static class ItemKeyedDataSource.LoadParams<Key> {
+ ctor public ItemKeyedDataSource.LoadParams(Key, int);
+ field public final Key key;
+ field public final int requestedLoadSize;
+ }
+
+ public abstract class PageKeyedDataSource<Key, Value> extends androidx.paging.DataSource {
+ ctor public PageKeyedDataSource();
+ method public abstract void loadAfter(androidx.paging.PageKeyedDataSource.LoadParams<Key>, androidx.paging.PageKeyedDataSource.LoadCallback<Key, Value>);
+ method public abstract void loadBefore(androidx.paging.PageKeyedDataSource.LoadParams<Key>, androidx.paging.PageKeyedDataSource.LoadCallback<Key, Value>);
+ method public abstract void loadInitial(androidx.paging.PageKeyedDataSource.LoadInitialParams<Key>, androidx.paging.PageKeyedDataSource.LoadInitialCallback<Key, Value>);
+ method public final <ToValue> androidx.paging.PageKeyedDataSource<Key, ToValue> map(androidx.arch.core.util.Function<Value, ToValue>);
+ method public final <ToValue> androidx.paging.PageKeyedDataSource<Key, ToValue> mapByPage(androidx.arch.core.util.Function<java.util.List<Value>, java.util.List<ToValue>>);
+ }
+
+ public static abstract class PageKeyedDataSource.LoadCallback<Key, Value> {
+ ctor public PageKeyedDataSource.LoadCallback();
+ method public abstract void onResult(java.util.List<Value>, Key);
+ }
+
+ public static abstract class PageKeyedDataSource.LoadInitialCallback<Key, Value> {
+ ctor public PageKeyedDataSource.LoadInitialCallback();
+ method public abstract void onResult(java.util.List<Value>, int, int, Key, Key);
+ method public abstract void onResult(java.util.List<Value>, Key, Key);
+ }
+
+ public static class PageKeyedDataSource.LoadInitialParams<Key> {
+ ctor public PageKeyedDataSource.LoadInitialParams(int, boolean);
+ field public final boolean placeholdersEnabled;
+ field public final int requestedLoadSize;
+ }
+
+ public static class PageKeyedDataSource.LoadParams<Key> {
+ ctor public PageKeyedDataSource.LoadParams(Key, int);
+ field public final Key key;
+ field public final int requestedLoadSize;
+ }
+
+ public abstract class PagedList<T> extends java.util.AbstractList {
+ method public void addWeakCallback(java.util.List<T>, androidx.paging.PagedList.Callback);
+ method public void detach();
+ method public T get(int);
+ method public androidx.paging.PagedList.Config getConfig();
+ method public abstract androidx.paging.DataSource<?, T> getDataSource();
+ method public abstract java.lang.Object getLastKey();
+ method public int getPositionOffset();
+ method public boolean isDetached();
+ method public boolean isImmutable();
+ method public void loadAround(int);
+ method public void removeWeakCallback(androidx.paging.PagedList.Callback);
+ method public int size();
+ method public java.util.List<T> snapshot();
+ }
+
+ public static abstract class PagedList.BoundaryCallback<T> {
+ ctor public PagedList.BoundaryCallback();
+ method public void onItemAtEndLoaded(T);
+ method public void onItemAtFrontLoaded(T);
+ method public void onZeroItemsLoaded();
+ }
+
+ public static final class PagedList.Builder<Key, Value> {
+ ctor public PagedList.Builder(androidx.paging.DataSource<Key, Value>, androidx.paging.PagedList.Config);
+ ctor public PagedList.Builder(androidx.paging.DataSource<Key, Value>, int);
+ method public androidx.paging.PagedList<Value> build();
+ method public androidx.paging.PagedList.Builder<Key, Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback);
+ method public androidx.paging.PagedList.Builder<Key, Value> setFetchExecutor(java.util.concurrent.Executor);
+ method public androidx.paging.PagedList.Builder<Key, Value> setInitialKey(Key);
+ method public androidx.paging.PagedList.Builder<Key, Value> setNotifyExecutor(java.util.concurrent.Executor);
+ }
+
+ public static abstract class PagedList.Callback {
+ ctor public PagedList.Callback();
+ method public abstract void onChanged(int, int);
+ method public abstract void onInserted(int, int);
+ method public abstract void onRemoved(int, int);
+ }
+
+ public static class PagedList.Config {
+ field public final boolean enablePlaceholders;
+ field public final int initialLoadSizeHint;
+ field public final int pageSize;
+ field public final int prefetchDistance;
+ }
+
+ public static final class PagedList.Config.Builder {
+ ctor public PagedList.Config.Builder();
+ method public androidx.paging.PagedList.Config build();
+ method public androidx.paging.PagedList.Config.Builder setEnablePlaceholders(boolean);
+ method public androidx.paging.PagedList.Config.Builder setInitialLoadSizeHint(int);
+ method public androidx.paging.PagedList.Config.Builder setPageSize(int);
+ method public androidx.paging.PagedList.Config.Builder setPrefetchDistance(int);
+ }
+
+ public abstract class PositionalDataSource<T> extends androidx.paging.DataSource {
+ ctor public PositionalDataSource();
+ method public static int computeInitialLoadPosition(androidx.paging.PositionalDataSource.LoadInitialParams, int);
+ method public static int computeInitialLoadSize(androidx.paging.PositionalDataSource.LoadInitialParams, int, int);
+ method public abstract void loadInitial(androidx.paging.PositionalDataSource.LoadInitialParams, androidx.paging.PositionalDataSource.LoadInitialCallback<T>);
+ method public abstract void loadRange(androidx.paging.PositionalDataSource.LoadRangeParams, androidx.paging.PositionalDataSource.LoadRangeCallback<T>);
+ method public final <V> androidx.paging.PositionalDataSource<V> map(androidx.arch.core.util.Function<T, V>);
+ method public final <V> androidx.paging.PositionalDataSource<V> mapByPage(androidx.arch.core.util.Function<java.util.List<T>, java.util.List<V>>);
+ }
+
+ public static abstract class PositionalDataSource.LoadInitialCallback<T> {
+ ctor public PositionalDataSource.LoadInitialCallback();
+ method public abstract void onResult(java.util.List<T>, int, int);
+ method public abstract void onResult(java.util.List<T>, int);
+ }
+
+ public static class PositionalDataSource.LoadInitialParams {
+ ctor public PositionalDataSource.LoadInitialParams(int, int, int, boolean);
+ field public final int pageSize;
+ field public final boolean placeholdersEnabled;
+ field public final int requestedLoadSize;
+ field public final int requestedStartPosition;
+ }
+
+ public static abstract class PositionalDataSource.LoadRangeCallback<T> {
+ ctor public PositionalDataSource.LoadRangeCallback();
+ method public abstract void onResult(java.util.List<T>);
+ }
+
+ public static class PositionalDataSource.LoadRangeParams {
+ ctor public PositionalDataSource.LoadRangeParams(int, int);
+ field public final int loadSize;
+ field public final int startPosition;
+ }
+
+}
+
diff --git a/paging/runtime/api/current.txt b/paging/runtime/api/current.txt
new file mode 100644
index 0000000..58c93a3
--- /dev/null
+++ b/paging/runtime/api/current.txt
@@ -0,0 +1,32 @@
+package androidx.paging {
+
+ public class AsyncPagedListDiffer<T> {
+ ctor public AsyncPagedListDiffer(androidx.recyclerview.widget.RecyclerView.Adapter, androidx.recyclerview.widget.DiffUtil.ItemCallback<T>);
+ ctor public AsyncPagedListDiffer(androidx.recyclerview.widget.ListUpdateCallback, androidx.recyclerview.widget.AsyncDifferConfig<T>);
+ method public androidx.paging.PagedList<T> getCurrentList();
+ method public T getItem(int);
+ method public int getItemCount();
+ method public void submitList(androidx.paging.PagedList<T>);
+ }
+
+ public final class LivePagedListBuilder<Key, Value> {
+ ctor public LivePagedListBuilder(androidx.paging.DataSource.Factory<Key, Value>, androidx.paging.PagedList.Config);
+ ctor public LivePagedListBuilder(androidx.paging.DataSource.Factory<Key, Value>, int);
+ method public androidx.lifecycle.LiveData<androidx.paging.PagedList<Value>> build();
+ method public androidx.paging.LivePagedListBuilder<Key, Value> setBoundaryCallback(androidx.paging.PagedList.BoundaryCallback<Value>);
+ method public androidx.paging.LivePagedListBuilder<Key, Value> setFetchExecutor(java.util.concurrent.Executor);
+ method public androidx.paging.LivePagedListBuilder<Key, Value> setInitialLoadKey(Key);
+ }
+
+ public abstract class PagedListAdapter<T, VH extends androidx.recyclerview.widget.RecyclerView.ViewHolder> extends androidx.recyclerview.widget.RecyclerView.Adapter {
+ ctor protected PagedListAdapter(androidx.recyclerview.widget.DiffUtil.ItemCallback<T>);
+ ctor protected PagedListAdapter(androidx.recyclerview.widget.AsyncDifferConfig<T>);
+ method public androidx.paging.PagedList<T> getCurrentList();
+ method protected T getItem(int);
+ method public int getItemCount();
+ method public void onCurrentListChanged(androidx.paging.PagedList<T>);
+ method public void submitList(androidx.paging.PagedList<T>);
+ }
+
+}
+
diff --git a/paging/runtime/build.gradle b/paging/runtime/build.gradle
index dd9189c..8329c05 100644
--- a/paging/runtime/build.gradle
+++ b/paging/runtime/build.gradle
@@ -48,4 +48,5 @@
inceptionYear = "2017"
description = "Android Paging-Runtime"
url = SupportLibraryExtension.ARCHITECTURE_URL
+ failOnUncheckedWarnings = false
}
diff --git a/paging/rxjava2/build.gradle b/paging/rxjava2/build.gradle
index f4c5308..2fd8caf 100644
--- a/paging/rxjava2/build.gradle
+++ b/paging/rxjava2/build.gradle
@@ -45,4 +45,5 @@
inceptionYear = "2018"
description = "Android Paging RXJava2"
url = SupportLibraryExtension.ARCHITECTURE_URL
+ failOnUncheckedWarnings = false
}
diff --git a/preference/build.gradle b/preference/build.gradle
index b7c6872..8518300 100644
--- a/preference/build.gradle
+++ b/preference/build.gradle
@@ -55,4 +55,6 @@
mavenGroup = LibraryGroups.PREFERENCE
inceptionYear = "2015"
description = "Android Support Preference v7"
+ failOnUncheckedWarnings = false
+ failOnDeprecationWarnings = false
}
diff --git a/print/build.gradle b/print/build.gradle
index 7901514..05919df 100644
--- a/print/build.gradle
+++ b/print/build.gradle
@@ -16,4 +16,5 @@
mavenGroup = LibraryGroups.PRINT
inceptionYear = "2018"
description = "The Support Library is a static library that you can add to your Android application in order to use APIs that are either not available for older platform versions or utility APIs that aren't a part of the framework APIs. Compatible on devices running API 14 or later."
+ failOnDeprecationWarnings = false
}
diff --git a/recommendation/build.gradle b/recommendation/build.gradle
index 84d0445..684726e 100644
--- a/recommendation/build.gradle
+++ b/recommendation/build.gradle
@@ -17,4 +17,5 @@
inceptionYear = "2015"
description = "Android Support Recommendation"
minSdkVersion = 21
+ failOnDeprecationWarnings = false
}
diff --git a/recyclerview-selection/OWNERS b/recyclerview-selection/OWNERS
new file mode 100644
index 0000000..779e918
--- /dev/null
+++ b/recyclerview-selection/OWNERS
@@ -0,0 +1 @@
+smckay@google.com
\ No newline at end of file
diff --git a/recyclerview-selection/api/current.txt b/recyclerview-selection/api/current.txt
index 0be9669..3d9bdf5 100644
--- a/recyclerview-selection/api/current.txt
+++ b/recyclerview-selection/api/current.txt
@@ -113,13 +113,13 @@
method public androidx.recyclerview.selection.SelectionTracker<K> build();
method public androidx.recyclerview.selection.SelectionTracker.Builder<K> withBandOverlay(int);
method public androidx.recyclerview.selection.SelectionTracker.Builder<K> withBandPredicate(androidx.recyclerview.selection.BandPredicate);
- method public androidx.recyclerview.selection.SelectionTracker.Builder<K> withBandTooltypes(int...);
method public androidx.recyclerview.selection.SelectionTracker.Builder<K> withFocusDelegate(androidx.recyclerview.selection.FocusDelegate<K>);
method public androidx.recyclerview.selection.SelectionTracker.Builder<K> withGestureTooltypes(int...);
method public androidx.recyclerview.selection.SelectionTracker.Builder<K> withOnContextClickListener(androidx.recyclerview.selection.OnContextClickListener);
method public androidx.recyclerview.selection.SelectionTracker.Builder<K> withOnDragInitiatedListener(androidx.recyclerview.selection.OnDragInitiatedListener);
method public androidx.recyclerview.selection.SelectionTracker.Builder<K> withOnItemActivatedListener(androidx.recyclerview.selection.OnItemActivatedListener<K>);
method public androidx.recyclerview.selection.SelectionTracker.Builder<K> withOperationMonitor(androidx.recyclerview.selection.OperationMonitor);
+ method public androidx.recyclerview.selection.SelectionTracker.Builder<K> withPointerTooltypes(int...);
method public androidx.recyclerview.selection.SelectionTracker.Builder<K> withSelectionPredicate(androidx.recyclerview.selection.SelectionTracker.SelectionPredicate<K>);
}
diff --git a/recyclerview-selection/build.gradle b/recyclerview-selection/build.gradle
index b467e48..dcda345 100644
--- a/recyclerview-selection/build.gradle
+++ b/recyclerview-selection/build.gradle
@@ -41,4 +41,6 @@
mavenGroup = LibraryGroups.RECYCLERVIEW
inceptionYear = "2017"
description = "Library providing item selection framework for RecyclerView. Support for touch based and band selection is provided."
+ failOnUncheckedWarnings = false
+ failOnDeprecationWarnings = false
}
diff --git a/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/GestureSelectionHelperTest.java b/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/GestureSelectionHelperTest.java
index 4c10930..9fd494d 100644
--- a/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/GestureSelectionHelperTest.java
+++ b/recyclerview-selection/src/androidTest/java/androidx/recyclerview/selection/GestureSelectionHelperTest.java
@@ -18,7 +18,6 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -56,17 +55,17 @@
private GestureSelectionHelper mHelper;
private SelectionTracker<String> mSelectionTracker;
private SelectionProbe mSelection;
- private OperationMonitor mLock;
+ private OperationMonitor mMonitor;
private TestViewDelegate mView;
@Before
public void setUp() {
mSelectionTracker = SelectionTrackers.createStringTracker("gesture-selection-test", 100);
mSelection = new SelectionProbe(mSelectionTracker);
- mLock = new OperationMonitor();
+ mMonitor = new OperationMonitor();
mView = new TestViewDelegate();
mHelper = new GestureSelectionHelper(
- mSelectionTracker, mView, new TestAutoScroller(), mLock);
+ mSelectionTracker, mView, new TestAutoScroller(), mMonitor);
}
@Test
@@ -78,12 +77,10 @@
@Test
public void testNoStartOnIllegalPosition() {
+ mView.mNextPosition = RecyclerView.NO_POSITION;
mHelper.onInterceptTouchEvent(null, DOWN);
- try {
- mHelper.start();
- fail("Should have thrown.");
- } catch (Exception expected) {
- }
+ mHelper.start();
+ assertFalse(mMonitor.isStarted());
}
@Test
diff --git a/recyclerview-selection/src/main/java/androidx/recyclerview/selection/BandSelectionHelper.java b/recyclerview-selection/src/main/java/androidx/recyclerview/selection/BandSelectionHelper.java
index 883fcbf..6aabd45 100644
--- a/recyclerview-selection/src/main/java/androidx/recyclerview/selection/BandSelectionHelper.java
+++ b/recyclerview-selection/src/main/java/androidx/recyclerview/selection/BandSelectionHelper.java
@@ -48,7 +48,7 @@
* the user interacts with items using their pointer (and the band). Selectable items that intersect
* with the band, both on and off screen, are selected on pointer up.
*
- * @see SelectionTracker.Builder#withBandTooltypes(int...) for details on the specific
+ * @see SelectionTracker.Builder#withPointerTooltypes(int...) for details on the specific
* tooltypes routed to this helper.
*
* @param <K> Selection key type. @see {@link StorageStrategy} for supported types.
diff --git a/recyclerview-selection/src/main/java/androidx/recyclerview/selection/GestureSelectionHelper.java b/recyclerview-selection/src/main/java/androidx/recyclerview/selection/GestureSelectionHelper.java
index a780bda..ea7ec16 100644
--- a/recyclerview-selection/src/main/java/androidx/recyclerview/selection/GestureSelectionHelper.java
+++ b/recyclerview-selection/src/main/java/androidx/recyclerview/selection/GestureSelectionHelper.java
@@ -75,7 +75,13 @@
*/
void start() {
checkState(!mStarted);
- checkState(mLastStartedItemPos > -1);
+ // See: b/70518185. It appears start() is being called via onLongPress
+ // even though we never received an intial handleInterceptedDownEvent
+ // where we would usually initialize mLastStartedItemPos.
+ if (mLastStartedItemPos < 0) {
+ Log.w(TAG, "Illegal state. Can't start without valid mLastStartedItemPos.");
+ return;
+ }
// Partner code in MotionInputHandler ensures items
// are selected and range established prior to
diff --git a/recyclerview-selection/src/main/java/androidx/recyclerview/selection/MotionEvents.java b/recyclerview-selection/src/main/java/androidx/recyclerview/selection/MotionEvents.java
index 90d79e6..bc47a76 100644
--- a/recyclerview-selection/src/main/java/androidx/recyclerview/selection/MotionEvents.java
+++ b/recyclerview-selection/src/main/java/androidx/recyclerview/selection/MotionEvents.java
@@ -104,6 +104,16 @@
return isMouseEvent(e) && isActionMove(e) && e.getButtonState() == 0;
}
+ /**
+ * Returns true if the event is a drag event (which is presumbaly, but not
+ * explicitly required to be a mouse event).
+ * @param e
+ */
+ static boolean isPointerDragEvent(MotionEvent e) {
+ return isPrimaryMouseButtonPressed(e)
+ && isActionMove(e);
+ }
+
private static boolean hasBit(int metaState, int bit) {
return (metaState & bit) != 0;
}
diff --git a/recyclerview-selection/src/main/java/androidx/recyclerview/selection/OnDragInitiatedListener.java b/recyclerview-selection/src/main/java/androidx/recyclerview/selection/OnDragInitiatedListener.java
index a479872..50d8f1b 100644
--- a/recyclerview-selection/src/main/java/androidx/recyclerview/selection/OnDragInitiatedListener.java
+++ b/recyclerview-selection/src/main/java/androidx/recyclerview/selection/OnDragInitiatedListener.java
@@ -16,31 +16,58 @@
package androidx.recyclerview.selection;
+import static androidx.recyclerview.selection.ItemDetailsLookup.ItemDetails;
+
+import android.content.ClipData;
import android.view.MotionEvent;
+import android.view.View;
import androidx.annotation.NonNull;
/**
- * Register an OnDragInitiatedListener to be notified of potential drag operations,
- * and to handle them.
+ * Register an OnDragInitiatedListener to be notified when user intent to perform drag and drop
+ * operations on an item or items has been detected. Handle these events using {@link View}
+ * support for Drag and drop.
+ *
+ * <p>
+ * See {@link View#startDragAndDrop(ClipData, View.DragShadowBuilder, Object, int)}
+ * for details.
*/
public interface OnDragInitiatedListener {
/**
- * Called when a drag is initiated. Touch input handler only considers
- * a drag to be initiated on long press on an existing selection,
- * as normal touch and drag events are strongly associated with scrolling of the view.
+ * Called when user intent to perform a drag and drop operation has been detected.
*
* <p>
- * Drag will only be initiated when the item under the event is already selected.
+ * The following circumstances are considered to be expressing drag and drop intent:
+ *
+ * <ol>
+ * <li>Long press on selected item.</li>
+ * <li>Click and drag in the {@link ItemDetails#inDragRegion(MotionEvent) drag region}
+ * of selected item with a pointer device.</li>
+ * <li>Click and drag in drag region of un-selected item with a pointer device.</li>
+ * </ol>
*
* <p>
* The RecyclerView item at the coordinates of the MotionEvent is not supplied as a parameter
- * to this method as there may be multiple items selected. Clients can obtain the current
- * list of selected items from {@link SelectionTracker#copySelection(MutableSelection)}.
+ * to this method as there may be multiple items selected or no items selected (as may be
+ * the case in pointer drive drag and drop.)
+ *
+ * <p>
+ * Obtain the current list of selected items from
+ * {@link SelectionTracker#copySelection(MutableSelection)}. If there is no selection
+ * get the item under the event using {@link ItemDetailsLookup#getItemDetails(MotionEvent)}.
+ *
+ * <p>
+ * Drag region used with pointer devices is specified by
+ * {@link ItemDetails#inDragRegion(MotionEvent)}
+ *
+ * <p>
+ * See {@link android.view.View#startDragAndDrop(ClipData, View.DragShadowBuilder, Object, int)}
+ * for details on drag and drop implementation.
*
* @param e the event associated with the drag.
- * @return true if the event was handled.
+ * @return true if drag and drop was initiated.
*/
boolean onDragInitiated(@NonNull MotionEvent e);
}
diff --git a/recyclerview-selection/src/main/java/androidx/recyclerview/selection/PointerDragEventInterceptor.java b/recyclerview-selection/src/main/java/androidx/recyclerview/selection/PointerDragEventInterceptor.java
new file mode 100644
index 0000000..46ec5dd
--- /dev/null
+++ b/recyclerview-selection/src/main/java/androidx/recyclerview/selection/PointerDragEventInterceptor.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2018 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 androidx.recyclerview.selection;
+
+import static androidx.core.util.Preconditions.checkArgument;
+
+import android.view.MotionEvent;
+
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.OnItemTouchListener;
+
+/**
+ * OnItemTouchListener that delegates drag events to a drag listener,
+ * else sends event to fallback {@link OnItemTouchListener}.
+ *
+ * <p>See {@link OnDragInitiatedListener} for details on implementing drag and drop.
+ */
+final class PointerDragEventInterceptor implements OnItemTouchListener {
+
+ private final ItemDetailsLookup mEventDetailsLookup;
+ private final OnDragInitiatedListener mDragListener;
+ private @Nullable OnItemTouchListener mDelegate;
+
+ PointerDragEventInterceptor(
+ ItemDetailsLookup eventDetailsLookup,
+ OnDragInitiatedListener dragListener,
+ @Nullable OnItemTouchListener delegate) {
+
+ checkArgument(eventDetailsLookup != null);
+ checkArgument(dragListener != null);
+
+ mEventDetailsLookup = eventDetailsLookup;
+ mDragListener = dragListener;
+ mDelegate = delegate;
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
+ if (MotionEvents.isPointerDragEvent(e) && mEventDetailsLookup.inItemDragRegion(e)) {
+ return mDragListener.onDragInitiated(e);
+ } else if (mDelegate != null) {
+ return mDelegate.onInterceptTouchEvent(rv, e);
+ }
+ return false;
+ }
+
+ @Override
+ public void onTouchEvent(RecyclerView rv, MotionEvent e) {
+ if (mDelegate != null) {
+ mDelegate.onTouchEvent(rv, e);
+ }
+ }
+
+ @Override
+ public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
+ if (mDelegate != null) {
+ mDelegate.onRequestDisallowInterceptTouchEvent(disallowIntercept);
+ }
+ }
+}
diff --git a/recyclerview-selection/src/main/java/androidx/recyclerview/selection/SelectionTracker.java b/recyclerview-selection/src/main/java/androidx/recyclerview/selection/SelectionTracker.java
index 2b35f5d..95700d2 100644
--- a/recyclerview-selection/src/main/java/androidx/recyclerview/selection/SelectionTracker.java
+++ b/recyclerview-selection/src/main/java/androidx/recyclerview/selection/SelectionTracker.java
@@ -29,6 +29,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.OnItemTouchListener;
import java.util.Set;
@@ -471,7 +472,7 @@
MotionEvent.TOOL_TYPE_UNKNOWN
};
- private int[] mBandToolTypes = new int[] {
+ private int[] mPointerToolTypes = new int[] {
MotionEvent.TOOL_TYPE_MOUSE
};
@@ -637,14 +638,16 @@
}
/**
- * Replaces default band selection tool-types. Defaults are:
+ * Replaces default pointer tool-types. Pointer tools
+ * are associated with band selection, and certain
+ * drag and drop behaviors. Defaults are:
* {@link MotionEvent#TOOL_TYPE_MOUSE}.
*
* @param toolTypes the tool types to be used
* @return this
*/
- public Builder<K> withBandTooltypes(int... toolTypes) {
- mBandToolTypes = toolTypes;
+ public Builder<K> withPointerTooltypes(int... toolTypes) {
+ mPointerToolTypes = toolTypes;
return this;
}
@@ -769,10 +772,12 @@
mOnItemActivatedListener,
mFocusDelegate);
- for (int toolType : mBandToolTypes) {
+ for (int toolType : mPointerToolTypes) {
gestureRouter.register(toolType, mouseHandler);
}
+ @Nullable BandSelectionHelper bandHelper = null;
+
// Band selection not supported in single select mode, or when key access
// is limited to anything less than the entire corpus.
if (mKeyProvider.hasAccess(ItemKeyProvider.SCOPE_MAPPED)
@@ -782,7 +787,7 @@
// necessarily models and caches list/grid information as the user's pointer
// interacts with the item in the RecyclerView. Selectable items that intersect
// with the band, both on and off screen, are selected.
- BandSelectionHelper bandHelper = BandSelectionHelper.create(
+ bandHelper = BandSelectionHelper.create(
mRecyclerView,
scroller,
mBandOverlayId,
@@ -792,10 +797,13 @@
mBandPredicate,
mFocusDelegate,
mMonitor);
+ }
- for (int toolType : mBandToolTypes) {
- eventRouter.register(toolType, bandHelper);
- }
+ OnItemTouchListener pointerEventHandler = new PointerDragEventInterceptor(
+ mDetailsLookup, mOnDragInitiatedListener, bandHelper);
+
+ for (int toolType : mPointerToolTypes) {
+ eventRouter.register(toolType, pointerEventHandler);
}
return tracker;
diff --git a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/RxCallableQueryResultBinder.kt b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/RxCallableQueryResultBinder.kt
index b94d0c7..32c2dc5 100644
--- a/room/compiler/src/main/kotlin/androidx/room/solver/query/result/RxCallableQueryResultBinder.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/solver/query/result/RxCallableQueryResultBinder.kt
@@ -36,36 +36,39 @@
/**
* Generic Result binder for Rx classes that accept a callable.
*/
-class RxCallableQueryResultBinder(val rxType: RxType,
- val typeArg: TypeMirror,
- adapter: QueryResultAdapter?)
- : QueryResultBinder(adapter) {
- override fun convertAndReturn(roomSQLiteQueryVar: String,
- canReleaseQuery: Boolean,
- dbField: FieldSpec,
- inTransaction: Boolean,
- scope: CodeGenScope) {
+class RxCallableQueryResultBinder(
+ private val rxType: RxType,
+ val typeArg: TypeMirror,
+ adapter: QueryResultAdapter?) : QueryResultBinder(adapter) {
+ override fun convertAndReturn(
+ roomSQLiteQueryVar: String,
+ canReleaseQuery: Boolean,
+ dbField: FieldSpec,
+ inTransaction: Boolean,
+ scope: CodeGenScope) {
val callable = TypeSpec.anonymousClassBuilder("").apply {
val typeName = typeArg.typeName()
superclass(ParameterizedTypeName.get(java.util.concurrent.Callable::class.typeName(),
typeName))
addMethod(createCallMethod(
roomSQLiteQueryVar = roomSQLiteQueryVar,
- canReleaseQuery = canReleaseQuery,
dbField = dbField,
inTransaction = inTransaction,
scope = scope))
+ if (canReleaseQuery) {
+ addMethod(createFinalizeMethod(roomSQLiteQueryVar))
+ }
}.build()
scope.builder().apply {
addStatement("return $T.fromCallable($L)", rxType.className, callable)
}
}
- private fun createCallMethod(roomSQLiteQueryVar: String,
- canReleaseQuery: Boolean,
- dbField: FieldSpec,
- inTransaction: Boolean,
- scope: CodeGenScope): MethodSpec {
+ private fun createCallMethod(
+ roomSQLiteQueryVar: String,
+ dbField: FieldSpec,
+ inTransaction: Boolean,
+ scope: CodeGenScope): MethodSpec {
val adapterScope = scope.fork()
return MethodSpec.methodBuilder("call").apply {
returns(typeArg.typeName())
@@ -99,15 +102,20 @@
}
nextControlFlow("finally").apply {
addStatement("$L.close()", cursorVar)
- if (canReleaseQuery) {
- addStatement("$L.release()", roomSQLiteQueryVar)
- }
}
endControlFlow()
transactionWrapper?.endTransactionWithControlFlow()
}.build()
}
+ private fun createFinalizeMethod(roomSQLiteQueryVar: String): MethodSpec {
+ return MethodSpec.methodBuilder("finalize").apply {
+ addModifiers(Modifier.PROTECTED)
+ addAnnotation(Override::class.java)
+ addStatement("$L.release()", roomSQLiteQueryVar)
+ }.build()
+ }
+
enum class RxType(val className: ClassName, val canBeNull: Boolean) {
SINGLE(RxJava2TypeNames.SINGLE, canBeNull = false),
MAYBE(RxJava2TypeNames.MAYBE, canBeNull = true);
diff --git a/room/compiler/src/main/kotlin/androidx/room/writer/DatabaseWriter.kt b/room/compiler/src/main/kotlin/androidx/room/writer/DatabaseWriter.kt
index 4acd316..de00b4a 100644
--- a/room/compiler/src/main/kotlin/androidx/room/writer/DatabaseWriter.kt
+++ b/room/compiler/src/main/kotlin/androidx/room/writer/DatabaseWriter.kt
@@ -59,6 +59,7 @@
private fun createClearAllTables(): MethodSpec {
val scope = CodeGenScope(this)
return MethodSpec.methodBuilder("clearAllTables").apply {
+ addStatement("super.assertNotMainThread()")
val dbVar = scope.getTmpVar("_db")
addStatement("final $T $L = super.getOpenHelper().getWritableDatabase()",
SupportDbTypeNames.DB, dbVar)
@@ -98,7 +99,10 @@
endControlFlow()
}
addStatement("$L.query($S).close()", dbVar, "PRAGMA wal_checkpoint(FULL)")
- addStatement("$L.execSQL($S)", dbVar, "VACUUM")
+ beginControlFlow("if (!$L.inTransaction())", dbVar).apply {
+ addStatement("$L.execSQL($S)", dbVar, "VACUUM")
+ }
+ endControlFlow()
}
endControlFlow()
}.build()
diff --git a/room/compiler/src/test/data/databasewriter/output/ComplexDatabase.java b/room/compiler/src/test/data/databasewriter/output/ComplexDatabase.java
index 7f82dcd..2c47342 100644
--- a/room/compiler/src/test/data/databasewriter/output/ComplexDatabase.java
+++ b/room/compiler/src/test/data/databasewriter/output/ComplexDatabase.java
@@ -93,6 +93,7 @@
@Override
public void clearAllTables() {
+ super.assertNotMainThread();
final SupportSQLiteDatabase _db = super.getOpenHelper().getWritableDatabase();
try {
super.beginTransaction();
@@ -101,7 +102,9 @@
} finally {
super.endTransaction();
_db.query("PRAGMA wal_checkpoint(FULL)").close();
- _db.execSQL("VACUUM");
+ if (!_db.inTransaction()) {
+ _db.execSQL("VACUUM");
+ }
}
}
diff --git a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/ClearAllTablesTest.java b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/ClearAllTablesTest.java
index 8bffdef..76cc06a 100644
--- a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/ClearAllTablesTest.java
+++ b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/ClearAllTablesTest.java
@@ -16,11 +16,13 @@
package androidx.room.integration.testapp.test;
+import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
import android.content.Context;
import android.database.Cursor;
@@ -133,6 +135,29 @@
@Test
@SmallTest
+ public void inTransaction() {
+ mDao.insertParent(new Parent(1, "A"));
+ assertThat(mDao.countParent(), is(1));
+ // Running clearAllTables in a transaction is not recommended, but we should not crash.
+ mDatabase.runInTransaction(() -> mDatabase.clearAllTables());
+ assertThat(mDao.countParent(), is(0));
+ }
+
+ @Test
+ @SmallTest
+ public void inMainThread() {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ try {
+ mDatabase.clearAllTables();
+ fail("Was expecting an exception");
+ } catch (IllegalStateException e) {
+ assertThat(e.getMessage(), containsString("main thread"));
+ }
+ });
+ }
+
+ @Test
+ @SmallTest
public void foreignKey() {
mDao.insertParent(new Parent(1, "A"));
mDao.insertChild(new Child(1, "a", 1));
@@ -187,12 +212,12 @@
db.dao().insertParent(new Parent(1, uuid));
assertThat(queryEncoding(db), is(equalTo("UTF-8")));
db.close();
- assertThat(containsString(file, uuid), is(true));
+ assertThat(fileContainsString(file, uuid), is(true));
db = Room.databaseBuilder(context, ClearAllTablesDatabase.class, dbName)
.setJournalMode(journalMode).build();
db.clearAllTables();
db.close();
- assertThat(containsString(file, uuid), is(false));
+ assertThat(fileContainsString(file, uuid), is(false));
}
private String queryEncoding(RoomDatabase db) {
@@ -208,7 +233,7 @@
}
}
- private boolean containsString(File file, String s) throws IOException {
+ private boolean fileContainsString(File file, String s) throws IOException {
final byte[] content = new byte[(int) file.length()];
final FileInputStream stream = new FileInputStream(file);
//noinspection TryFinallyCanBeTryWithResources
diff --git a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/RxJava2Test.java b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/RxJava2Test.java
index 9878cd2..5ea9efc 100644
--- a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/RxJava2Test.java
+++ b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/RxJava2Test.java
@@ -40,6 +40,9 @@
import java.util.Collections;
import java.util.List;
+import io.reactivex.Flowable;
+import io.reactivex.Maybe;
+import io.reactivex.Single;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Predicate;
import io.reactivex.observers.TestObserver;
@@ -135,6 +138,42 @@
}
@Test
+ public void maybeUsers_keepMaybeReference() throws InterruptedException {
+ User[] users = TestUtil.createUsersArray(1, 2);
+ mUserDao.insertAll(users);
+ TestObserver<User> testObserver1 = new TestObserver<>();
+ Maybe<User> maybe1 = mUserDao.maybeUserById(1);
+ Disposable disposable1 = maybe1.observeOn(mTestScheduler)
+ .subscribeWith(testObserver1);
+ drain();
+ testObserver1.assertComplete();
+ // since this is a clean db, it is ok to rely on the order for the test.
+ testObserver1.assertValue(users[0]);
+
+ TestObserver<User> testObserver2 = new TestObserver<>();
+ Maybe<User> maybe2 = mUserDao.maybeUserById(2);
+ Disposable disposable2 = maybe2.observeOn(mTestScheduler)
+ .subscribeWith(testObserver2);
+ drain();
+ testObserver2.assertComplete();
+ // since this is a clean db, it is ok to rely on the order for the test.
+ testObserver2.assertValue(users[1]);
+
+ TestObserver<User> testObserver3 = new TestObserver<>();
+
+ Disposable disposable3 = maybe1.observeOn(mTestScheduler)
+ .subscribeWith(testObserver3);
+ drain();
+ testObserver3.assertComplete();
+ // since this is a clean db, it is ok to rely on the order for the test.
+ testObserver3.assertValue(users[0]);
+
+ disposable1.dispose();
+ disposable2.dispose();
+ disposable3.dispose();
+ }
+
+ @Test
public void singleUser_Empty() throws InterruptedException {
TestObserver<User> testObserver = new TestObserver<>();
Disposable disposable = mUserDao.singleUserById(3).observeOn(mTestScheduler)
@@ -186,6 +225,40 @@
}
@Test
+ public void singleUser_keepSingleReference() throws InterruptedException {
+ User[] users = TestUtil.createUsersArray(1, 2);
+ mUserDao.insertAll(users);
+ TestObserver<User> testObserver1 = new TestObserver<>();
+ Single<User> userSingle1 = mUserDao.singleUserById(1);
+ Disposable disposable1 = userSingle1.observeOn(mTestScheduler)
+ .subscribeWith(testObserver1);
+ drain();
+ testObserver1.assertComplete();
+ testObserver1.assertValue(users[0]);
+ disposable1.dispose();
+
+ // how get single for 2
+ TestObserver<User> testObserver2 = new TestObserver<>();
+ Single<User> userSingle2 = mUserDao.singleUserById(2);
+ Disposable disposable2 = userSingle2.observeOn(mTestScheduler)
+ .subscribeWith(testObserver2);
+ drain();
+ testObserver2.assertComplete();
+ testObserver2.assertValue(users[1]);
+ disposable2.dispose();
+
+ // now re-use the first single
+ TestObserver<User> testObserver3 = new TestObserver<>();
+ Disposable disposable3 = userSingle1.observeOn(mTestScheduler)
+ .subscribeWith(testObserver3);
+ drain();
+ testObserver3.assertComplete();
+ testObserver3.assertValue(users[0]);
+ disposable3.dispose();
+ }
+
+
+ @Test
public void observeOnce() throws InterruptedException {
User user = TestUtil.createUser(3);
mUserDao.insert(user);
@@ -239,6 +312,33 @@
}
@Test
+ public void observeFlowable_keepReference() throws InterruptedException {
+ User[] users = TestUtil.createUsersArray(1, 2);
+ mUserDao.insertAll(users);
+ drain();
+
+ TestSubscriber<User> consumer1 = new TestSubscriber<>();
+ Flowable<User> flowable1 = mUserDao.flowableUserById(1);
+ Disposable disposable1 = flowable1.subscribeWith(consumer1);
+ drain();
+ consumer1.assertValue(users[0]);
+
+ TestSubscriber<User> consumer2 = new TestSubscriber<>();
+ Disposable disposable2 = mUserDao.flowableUserById(2).subscribeWith(consumer2);
+ drain();
+ consumer2.assertValue(users[1]);
+
+ TestSubscriber<User> consumer3 = new TestSubscriber<>();
+ Disposable disposable3 = flowable1.subscribeWith(consumer3);
+ drain();
+ consumer3.assertValue(users[0]);
+
+ disposable1.dispose();
+ disposable2.dispose();
+ disposable3.dispose();
+ }
+
+ @Test
public void flowableCountUsers() throws InterruptedException {
TestSubscriber<Integer> consumer = new TestSubscriber<>();
mUserDao.flowableCountUsers()
diff --git a/samples/SupportCarDemos/src/main/AndroidManifest.xml b/samples/SupportCarDemos/src/main/AndroidManifest.xml
index 00e4ebb..64085e4 100644
--- a/samples/SupportCarDemos/src/main/AndroidManifest.xml
+++ b/samples/SupportCarDemos/src/main/AndroidManifest.xml
@@ -106,6 +106,28 @@
<meta-data android:name="android.support.PARENT_ACTIVITY"
android:value=".SupportCarDemoActivity" />
</activity>
+
+ <activity android:name=".CarAlertDialogDemo"
+ android:label="CarAlertDialogDemo"
+ android:parentActivityName=".SupportCarDemoActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ <meta-data android:name="android.support.PARENT_ACTIVITY"
+ android:value=".SupportCarDemoActivity" />
+ </activity>
+
+ <activity android:name=".CarListDialogDemo"
+ android:label="CarListDialogDemo"
+ android:parentActivityName=".SupportCarDemoActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ <meta-data android:name="android.support.PARENT_ACTIVITY"
+ android:value=".SupportCarDemoActivity" />
+ </activity>
</application>
</manifest>
diff --git a/samples/SupportCarDemos/src/main/java/com/example/androidx/car/CarAlertDialogDemo.java b/samples/SupportCarDemos/src/main/java/com/example/androidx/car/CarAlertDialogDemo.java
new file mode 100644
index 0000000..e852d0f
--- /dev/null
+++ b/samples/SupportCarDemos/src/main/java/com/example/androidx/car/CarAlertDialogDemo.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2018 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.example.androidx.car;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.os.Bundle;
+import android.widget.CheckBox;
+
+import androidx.car.app.CarAlertDialog;
+import androidx.fragment.app.DialogFragment;
+import androidx.fragment.app.FragmentActivity;
+
+/**
+ * A demo activity that will display a {@link CarAlertDialog} with configurable options for what is
+ * in the contents of that resulting dialog.
+ */
+public class CarAlertDialogDemo extends FragmentActivity {
+ private static final String DIALOG_TAG = "alert_dialog_tag";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.alert_dialog_activity);
+
+ CheckBox hasTitleView = findViewById(R.id.has_title);
+ CheckBox hasBodyText = findViewById(R.id.has_body_text);
+ CheckBox hasAction1 = findViewById(R.id.has_action_1);
+ CheckBox hasAction2 = findViewById(R.id.has_action_2);
+
+ findViewById(R.id.create_dialog).setOnClickListener(v -> {
+ AlertDialogFragment alertDialog = AlertDialogFragment.newInstance(
+ hasTitleView.isChecked(),
+ hasBodyText.isChecked(),
+ hasAction1.isChecked(),
+ hasAction2.isChecked());
+
+ alertDialog.show(getSupportFragmentManager(), DIALOG_TAG);
+ });
+ }
+
+ /** A {@link DialogFragment} that will inflate a {@link CarAlertDialog}. */
+ public static class AlertDialogFragment extends DialogFragment {
+ private static final String HAS_TITLE_KEY = "has_title_key";
+ private static final String HAS_BODY_KEY = "has_body_key";
+ private static final String HAS_ACTION_1_KEY = "has_action_1_key";
+ private static final String HAS_ACTION_2_KEY = "has_action_2_key";
+
+ static AlertDialogFragment newInstance(boolean hasTitle,
+ boolean hasBody, boolean hasAction1, boolean hasAction2) {
+ Bundle args = new Bundle();
+ args.putBoolean(HAS_TITLE_KEY, hasTitle);
+ args.putBoolean(HAS_BODY_KEY, hasBody);
+ args.putBoolean(HAS_ACTION_1_KEY, hasAction1);
+ args.putBoolean(HAS_ACTION_2_KEY, hasAction2);
+
+ AlertDialogFragment fragment = new AlertDialogFragment();
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ Context context = getContext();
+ Bundle args = getArguments();
+ CarAlertDialog.Builder builder = new CarAlertDialog.Builder(context);
+
+ if (args.getBoolean(HAS_TITLE_KEY)) {
+ builder.setTitle(context.getString(R.string.alert_dialog_title));
+ }
+
+ if (args.getBoolean(HAS_BODY_KEY)) {
+ builder.setBody(context.getString(R.string.alert_dialog_body));
+ }
+
+ if (args.getBoolean(HAS_ACTION_1_KEY)) {
+ builder.setPositiveButton(context.getString(R.string.alert_dialog_action1),
+ /* listener= */ null);
+ }
+
+ if (args.getBoolean(HAS_ACTION_2_KEY)) {
+ builder.setNegativeButton(context.getString(R.string.alert_dialog_action2),
+ /* listener= */ null);
+ }
+
+ return builder.create();
+ }
+ }
+}
diff --git a/samples/SupportCarDemos/src/main/java/com/example/androidx/car/CarListDialogDemo.java b/samples/SupportCarDemos/src/main/java/com/example/androidx/car/CarListDialogDemo.java
new file mode 100644
index 0000000..4e43cd5
--- /dev/null
+++ b/samples/SupportCarDemos/src/main/java/com/example/androidx/car/CarListDialogDemo.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2018 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.example.androidx.car;
+
+import android.app.Dialog;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.widget.EditText;
+
+import androidx.annotation.NonNull;
+import androidx.car.app.CarListDialog;
+import androidx.fragment.app.DialogFragment;
+import androidx.fragment.app.FragmentActivity;
+
+/**
+ * A demo activity that will display a {@link CarListDialog} with configurable options for what is
+ * in the contents of that resulting dialog.
+ */
+public class CarListDialogDemo extends FragmentActivity {
+ private static final String DIALOG_TAG = "list_dialog_tag";
+
+ private static final int DEFAULT_NUM_OF_ITEMS = 4;
+ private static final int DEFAULT_INITIAL_POSITION = 0;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.list_dialog_activity);
+
+ EditText numOfItemsEdit = findViewById(R.id.num_of_items_edit);
+ EditText initialPositionEdit = findViewById(R.id.initial_position_edit);
+
+ findViewById(R.id.create_dialog).setOnClickListener(v -> {
+ CharSequence numOfItemsText = numOfItemsEdit.getText();
+ int numOfItems = TextUtils.isEmpty(numOfItemsText)
+ ? DEFAULT_NUM_OF_ITEMS
+ : Integer.parseInt(numOfItemsText.toString());
+
+ CharSequence initialPositionText = initialPositionEdit.getText();
+ int initialPosition = TextUtils.isEmpty(initialPositionText)
+ ? DEFAULT_INITIAL_POSITION
+ : Integer.parseInt(initialPositionText.toString());
+
+ ListDialogFragment alertDialog = ListDialogFragment.newInstance(
+ numOfItems, initialPosition);
+
+ alertDialog.show(getSupportFragmentManager(), DIALOG_TAG);
+ });
+ }
+
+ /** A {@link DialogFragment} that will inflate a {@link CarListDialog}. */
+ public static class ListDialogFragment extends DialogFragment {
+ private static final String NUM_OF_ITEMS_KEY = "num_of_items_key";
+ private static final String INITIAL_POSITION_KEY = "initial_position_key";
+
+ static ListDialogFragment newInstance(int numOfItems, int initialPosition) {
+ Bundle args = new Bundle();
+ args.putInt(NUM_OF_ITEMS_KEY, numOfItems);
+ args.putInt(INITIAL_POSITION_KEY, initialPosition);
+
+ ListDialogFragment fragment = new ListDialogFragment();
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ @NonNull
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ return new CarListDialog.Builder(getContext())
+ .setItems(getItems(), /* onClickListener= */ null)
+ .setInitialPosition(getArguments().getInt(INITIAL_POSITION_KEY))
+ .create();
+ }
+
+ private String[] getItems() {
+ int numOfItems = getArguments().getInt(NUM_OF_ITEMS_KEY);
+
+ String[] items = new String[numOfItems];
+ for (int i = 0; i < numOfItems; i++) {
+ items[i] = "Item " + (i + 1);
+ }
+ return items;
+ }
+ }
+}
diff --git a/samples/SupportCarDemos/src/main/res/layout/alert_dialog_activity.xml b/samples/SupportCarDemos/src/main/res/layout/alert_dialog_activity.xml
new file mode 100644
index 0000000..4f881f8
--- /dev/null
+++ b/samples/SupportCarDemos/src/main/res/layout/alert_dialog_activity.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright 2018 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.
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:gravity="center"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <CheckBox
+ android:id="@+id/has_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/car_padding_4"
+ android:checked="true"
+ android:textSize="@dimen/car_body1_size"
+ android:text="@string/alert_dialog_checkbox_title" />
+
+ <CheckBox
+ android:id="@+id/has_body_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/car_padding_4"
+ android:checked="true"
+ android:textSize="@dimen/car_body1_size"
+ android:text="@string/alert_dialog_checkbox_body" />
+
+ <CheckBox
+ android:id="@+id/has_action_1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/car_padding_4"
+ android:checked="true"
+ android:textSize="@dimen/car_body1_size"
+ android:text="@string/alert_dialog_checkbox_action1" />
+
+ <CheckBox
+ android:id="@+id/has_action_2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="@dimen/car_padding_4"
+ android:checked="true"
+ android:textSize="@dimen/car_body1_size"
+ android:text="@string/alert_dialog_checkbox_action2" />
+
+ <Button
+ android:id="@+id/create_dialog"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:checked="true"
+ android:text="@string/create_alert_dialog_button"
+ style="@style/Widget.Car.Button" />
+</LinearLayout>
diff --git a/samples/SupportCarDemos/src/main/res/layout/list_dialog_activity.xml b/samples/SupportCarDemos/src/main/res/layout/list_dialog_activity.xml
new file mode 100644
index 0000000..d68ed82
--- /dev/null
+++ b/samples/SupportCarDemos/src/main/res/layout/list_dialog_activity.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright 2018 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.
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:orientation="vertical"
+ android:gravity="center"
+ android:background="@color/car_card"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingStart="@dimen/car_margin"
+ android:paddingEnd="@dimen/car_margin" >
+
+ <android.support.design.widget.TextInputLayout
+ android:id="@+id/num_of_items"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/car_single_line_list_item_height"
+ android:hint="@string/list_dialog_num_of_items_hint"
+ app:hintTextAppearance="@style/TextAppearance.Car.Hint">
+
+ <android.support.design.widget.TextInputEditText
+ android:id="@+id/num_of_items_edit"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:inputType="number"
+ android:maxLines="1"
+ android:textAppearance="@style/TextAppearance.Car.Body2"/>
+ </android.support.design.widget.TextInputLayout>
+
+ <android.support.design.widget.TextInputLayout
+ android:id="@+id/initial_position"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/car_single_line_list_item_height"
+ android:hint="@string/list_dialog_initial_position_hint"
+ app:hintTextAppearance="@style/TextAppearance.Car.Hint">
+
+ <android.support.design.widget.TextInputEditText
+ android:id="@+id/initial_position_edit"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:inputType="number"
+ android:maxLines="1"
+ android:textAppearance="@style/TextAppearance.Car.Body2"/>
+ </android.support.design.widget.TextInputLayout>
+
+ <Button
+ android:id="@+id/create_dialog"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:checked="true"
+ android:text="@string/create_list_dialog_button"
+ style="@style/Widget.Car.Button" />
+</LinearLayout>
diff --git a/samples/SupportCarDemos/src/main/res/values/strings.xml b/samples/SupportCarDemos/src/main/res/values/strings.xml
index 9a6fc1a..6d1dade 100644
--- a/samples/SupportCarDemos/src/main/res/values/strings.xml
+++ b/samples/SupportCarDemos/src/main/res/values/strings.xml
@@ -54,5 +54,22 @@
<string name="drawer_demo_activity_title">Drawer Demo</string>
<string name="drawer_demo_root_item_label">Item %1$d</string>
<string name="drawer_demo_subitem_label">SubItem %1$d</string>
+
+ <!-- Strings for CarAlertDialog Demo. -->
+ <string name="alert_dialog_checkbox_title">Title</string>
+ <string name="alert_dialog_checkbox_body">Body</string>
+ <string name="alert_dialog_checkbox_action1">Action 1</string>
+ <string name="alert_dialog_checkbox_action2">Action 2</string>
+ <string name="create_alert_dialog_button">Create CarAlertDialog</string>
+
+ <string name="alert_dialog_title">Title</string>
+ <string name="alert_dialog_body">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec fringilla orci id nulla facilisis, sed luctus massa consectetur. Vivamus sagittis leo eget ultrices malesuada. Duis hendrerit nibh non pretium tincidunt.</string>
+ <string name="alert_dialog_action1">Action 1</string>
+ <string name="alert_dialog_action2">Action 2</string>
+
+ <!-- Strings for CarListDialog Demo. -->
+ <string name="list_dialog_num_of_items_hint">Number of Items</string>
+ <string name="list_dialog_initial_position_hint">Initial Position</string>
+ <string name="create_list_dialog_button">Create CarListDialog</string>
</resources>
diff --git a/slices/builders/build.gradle b/slices/builders/build.gradle
index 907a0b4..a9624b2 100644
--- a/slices/builders/build.gradle
+++ b/slices/builders/build.gradle
@@ -36,4 +36,6 @@
inceptionYear = "2017"
description = "A set of builders to create templates using SliceProvider APIs"
minSdkVersion = 19
+ failOnUncheckedWarnings = false
+ failOnDeprecationWarnings = false
}
diff --git a/slices/core/build.gradle b/slices/core/build.gradle
index cb17394..0530edd 100644
--- a/slices/core/build.gradle
+++ b/slices/core/build.gradle
@@ -40,4 +40,6 @@
inceptionYear = "2017"
description = "The slices core library provides utilities for the slices view and provider libraries"
minSdkVersion = 19
+ failOnUncheckedWarnings = false
+ failOnDeprecationWarnings = false
}
diff --git a/slices/view/build.gradle b/slices/view/build.gradle
index 71de3a7..5836d20 100644
--- a/slices/view/build.gradle
+++ b/slices/view/build.gradle
@@ -34,9 +34,6 @@
androidTestImplementation(DEXMAKER_MOCKITO, libs.exclude_bytebuddy)
}
-android {
-}
-
supportLibrary {
name = "Slice views"
publish = true
@@ -45,4 +42,6 @@
inceptionYear = "2017"
description = "A library that handles rendering of slice content into supported templates"
minSdkVersion = 19
+ failOnUncheckedWarnings = false
+ failOnDeprecationWarnings = false
}
diff --git a/testutils/build.gradle b/testutils/build.gradle
index e0c4139..f39248e 100644
--- a/testutils/build.gradle
+++ b/testutils/build.gradle
@@ -36,3 +36,7 @@
disable 'InvalidPackage' // Lint is unhappy about junit package
}
}
+
+supportLibrary {
+ failOnUncheckedWarnings = false
+}
\ No newline at end of file
diff --git a/textclassifier/build.gradle b/textclassifier/build.gradle
index fd654ee..fcaa89d 100644
--- a/textclassifier/build.gradle
+++ b/textclassifier/build.gradle
@@ -24,4 +24,5 @@
inceptionYear = "2018"
description = "The TextClassifier Support Library can be added to an Android application in order to use the TextClassifier API introduced in Android O on all devices with API level 14 or later."
minSdkVersion = 14
+ failOnUncheckedWarnings = false
}
diff --git a/transition/build.gradle b/transition/build.gradle
index 3e4e7d1..61c690f 100644
--- a/transition/build.gradle
+++ b/transition/build.gradle
@@ -36,4 +36,5 @@
mavenGroup = LibraryGroups.TRANSITION
inceptionYear = "2016"
description = "Android Transition Support Library"
+ failOnDeprecationWarnings = false
}
diff --git a/tv-provider/build.gradle b/tv-provider/build.gradle
index 9fe5f93..469f06d 100644
--- a/tv-provider/build.gradle
+++ b/tv-provider/build.gradle
@@ -23,4 +23,6 @@
inceptionYear = "2017"
description = "Android Support Library for TV Provider"
minSdkVersion = 21
+ failOnUncheckedWarnings = false
+ failOnDeprecationWarnings = false
}
\ No newline at end of file
diff --git a/v7/appcompat/build.gradle b/v7/appcompat/build.gradle
index a2ca59a..b04bee6 100644
--- a/v7/appcompat/build.gradle
+++ b/v7/appcompat/build.gradle
@@ -53,4 +53,6 @@
mavenGroup = LibraryGroups.APPCOMPAT
inceptionYear = "2011"
description = "The Support Library is a static library that you can add to your Android application in order to use APIs that are either not available for older platform versions or utility APIs that aren\'t a part of the framework APIs. Compatible on devices running API 14 or later."
+ failOnUncheckedWarnings = false
+ failOnDeprecationWarnings = false
}
diff --git a/v7/recyclerview/build.gradle b/v7/recyclerview/build.gradle
index 3e93b4e..ab5b778 100644
--- a/v7/recyclerview/build.gradle
+++ b/v7/recyclerview/build.gradle
@@ -42,4 +42,6 @@
mavenGroup = LibraryGroups.RECYCLERVIEW
inceptionYear = "2014"
description = "Android Support RecyclerView v7"
+ failOnUncheckedWarnings = false
+ failOnDeprecationWarnings = false
}
diff --git a/viewpager/build.gradle b/viewpager/build.gradle
index 02b45ba..6ba1d4d 100644
--- a/viewpager/build.gradle
+++ b/viewpager/build.gradle
@@ -24,4 +24,5 @@
mavenGroup = LibraryGroups.VIEWPAGER
inceptionYear = "2018"
description = "The Support Library is a static library that you can add to your Android application in order to use APIs that are either not available for older platform versions or utility APIs that aren't a part of the framework APIs. Compatible on devices running API 14 or later."
+ failOnDeprecationWarnings = false
}
diff --git a/wear/build.gradle b/wear/build.gradle
index c70ebef..0f606f1 100644
--- a/wear/build.gradle
+++ b/wear/build.gradle
@@ -42,4 +42,5 @@
inceptionYear = "2016"
description = "Android Wear Support UI"
minSdkVersion = 23
+ failOnDeprecationWarnings = false
}
diff --git a/webkit/build.gradle b/webkit/build.gradle
index d610dad..78a585e 100644
--- a/webkit/build.gradle
+++ b/webkit/build.gradle
@@ -51,4 +51,5 @@
mavenGroup = LibraryGroups.WEBKIT
inceptionYear = "2017"
description = "The WebView Support Library is a static library you can add to your Android application in order to use android.webkit APIs that are not available for older platform versions."
+ failOnUncheckedWarnings = false
}
diff --git a/webkit/src/androidTest/java/androidx/webkit/IncompatibilityTest.java b/webkit/src/androidTest/java/androidx/webkit/IncompatibilityTest.java
new file mode 100644
index 0000000..09424c6
--- /dev/null
+++ b/webkit/src/androidTest/java/androidx/webkit/IncompatibilityTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2018 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 androidx.webkit;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import android.support.test.filters.MediumTest;
+import android.support.test.filters.SdkSuppress;
+import android.support.test.runner.AndroidJUnit4;
+
+import androidx.webkit.internal.WebViewFeatureInternal;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests ensuring that Android versions/setups that are incompatible with the WebView Support
+ * Library are handled gracefully.
+ *
+ * Only L+ Android versions are compatible with the WebView Support Library, so any tests in this
+ * class that guarantee certain behaviour for incompatible Android versions will only be run on
+ * pre-L devices.
+ */
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class IncompatibilityTest {
+ @Test
+ @SdkSuppress(maxSdkVersion = 20)
+ public void testPreLDeviceHasNoWebViewFeatures() {
+ assertEquals(0, WebViewFeatureInternal.getWebViewApkFeaturesForTesting().length);
+ }
+
+ @Test
+ @SdkSuppress(maxSdkVersion = 20)
+ public void testPreLDeviceDoesNotSupportVisualStateCallback() {
+ assertFalse(WebViewFeature.isFeatureSupported(WebViewFeature.VISUAL_STATE_CALLBACK));
+ }
+}
diff --git a/webkit/src/androidTest/java/androidx/webkit/WebViewCompatTest.java b/webkit/src/androidTest/java/androidx/webkit/WebViewCompatTest.java
index bd77fdb..893b6df 100644
--- a/webkit/src/androidTest/java/androidx/webkit/WebViewCompatTest.java
+++ b/webkit/src/androidTest/java/androidx/webkit/WebViewCompatTest.java
@@ -29,7 +29,6 @@
import android.os.Looper;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
-import android.support.test.filters.Suppress;
import android.support.test.runner.AndroidJUnit4;
import android.webkit.SafeBrowsingResponse;
import android.webkit.ValueCallback;
@@ -85,9 +84,12 @@
assertTrue(callbackLatch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS));
}
- @Suppress // TODO(gsennton) remove @Suppress when b/76202025 has been resolved
@Test
public void testCheckThread() {
+ if (!WebViewFeature.isFeatureSupported(WebViewFeature.VISUAL_STATE_CALLBACK)) {
+ // Skip this test if VisualStateCallback is not supported.
+ return;
+ }
try {
WebViewCompat.postVisualStateCallback(mWebViewOnUiThread.getWebViewOnCurrentThread(), 5,
new WebViewCompat.VisualStateCallback() {
diff --git a/webkit/src/main/java/androidx/webkit/WebViewCompat.java b/webkit/src/main/java/androidx/webkit/WebViewCompat.java
index 88de335..7cb0bfd 100644
--- a/webkit/src/main/java/androidx/webkit/WebViewCompat.java
+++ b/webkit/src/main/java/androidx/webkit/WebViewCompat.java
@@ -32,7 +32,7 @@
import androidx.webkit.internal.WebViewFeatureInternal;
import androidx.webkit.internal.WebViewGlueCommunicator;
import androidx.webkit.internal.WebViewProviderAdapter;
-import androidx.webkit.internal.WebViewProviderFactoryAdapter;
+import androidx.webkit.internal.WebViewProviderFactory;
import org.chromium.support_lib_boundary.WebViewProviderBoundaryInterface;
@@ -307,7 +307,7 @@
return new WebViewProviderAdapter(createProvider(webview));
}
- private static WebViewProviderFactoryAdapter getFactory() {
+ private static WebViewProviderFactory getFactory() {
return WebViewGlueCommunicator.getFactory();
}
diff --git a/webkit/src/main/java/androidx/webkit/internal/IncompatibleApkWebViewProviderFactory.java b/webkit/src/main/java/androidx/webkit/internal/IncompatibleApkWebViewProviderFactory.java
new file mode 100644
index 0000000..71d5768
--- /dev/null
+++ b/webkit/src/main/java/androidx/webkit/internal/IncompatibleApkWebViewProviderFactory.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2018 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 androidx.webkit.internal;
+
+import android.webkit.WebView;
+
+import org.chromium.support_lib_boundary.ServiceWorkerControllerBoundaryInterface;
+import org.chromium.support_lib_boundary.StaticsBoundaryInterface;
+import org.chromium.support_lib_boundary.WebViewProviderBoundaryInterface;
+import org.chromium.support_lib_boundary.WebkitToCompatConverterBoundaryInterface;
+
+/**
+ * This is a stub class used when the WebView Support Library is invoked on a device incompatible
+ * with the library (either a pre-L device or a device without a compatible WebView APK).
+ * The only method in this class that should be called is {@link #getWebViewFeatures()}.
+ */
+public class IncompatibleApkWebViewProviderFactory implements WebViewProviderFactory {
+ private static final String[] EMPTY_STRING_ARRAY = new String[0];
+ private static final String UNSUPPORTED_EXCEPTION_EXPLANATION =
+ "This should never happen, if this method was called it means we're trying to reach "
+ + "into WebView APK code on an incompatible device. This most likely means the current "
+ + "method is being called too early, or is being called on start-up rather than lazily";
+
+ @Override
+ public WebViewProviderBoundaryInterface createWebView(WebView webview) {
+ throw new UnsupportedOperationException(UNSUPPORTED_EXCEPTION_EXPLANATION);
+ }
+
+ @Override
+ public WebkitToCompatConverterBoundaryInterface getWebkitToCompatConverter() {
+ throw new UnsupportedOperationException(UNSUPPORTED_EXCEPTION_EXPLANATION);
+ }
+
+ @Override
+ public StaticsBoundaryInterface getStatics() {
+ throw new UnsupportedOperationException(UNSUPPORTED_EXCEPTION_EXPLANATION);
+ }
+
+ @Override
+ public String[] getWebViewFeatures() {
+ return EMPTY_STRING_ARRAY;
+ }
+
+ @Override
+ public ServiceWorkerControllerBoundaryInterface getServiceWorkerController() {
+ throw new UnsupportedOperationException(UNSUPPORTED_EXCEPTION_EXPLANATION);
+ }
+}
diff --git a/webkit/src/main/java/androidx/webkit/internal/SupportLibraryInfo.java b/webkit/src/main/java/androidx/webkit/internal/SupportLibraryInfo.java
deleted file mode 100644
index da8a02c..0000000
--- a/webkit/src/main/java/androidx/webkit/internal/SupportLibraryInfo.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2018 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 androidx.webkit.internal;
-
-import org.chromium.support_lib_boundary.SupportLibraryInfoBoundaryInterface;
-import org.chromium.support_lib_boundary.util.Features;
-
-/**
- * Contains information about the Android Support Library part of the WebView Support Library - this
- * information is passed to the WebView APK code with the first WebView Support Library call.
- */
-public class SupportLibraryInfo implements SupportLibraryInfoBoundaryInterface {
- // Features supported by the support library itself (regardless of what the WebView APK
- // supports).
- private static final String[] SUPPORTED_FEATURES =
- new String[] {
- Features.VISUAL_STATE_CALLBACK
- };
-
- @Override
- public String[] getSupportedFeatures() {
- return SUPPORTED_FEATURES;
- }
-}
diff --git a/webkit/src/main/java/androidx/webkit/internal/WebViewFeatureInternal.java b/webkit/src/main/java/androidx/webkit/internal/WebViewFeatureInternal.java
index d16713c..74f67e4 100644
--- a/webkit/src/main/java/androidx/webkit/internal/WebViewFeatureInternal.java
+++ b/webkit/src/main/java/androidx/webkit/internal/WebViewFeatureInternal.java
@@ -77,6 +77,11 @@
WebViewGlueCommunicator.getFactory().getWebViewFeatures();
}
+
+ public static String[] getWebViewApkFeaturesForTesting() {
+ return LAZY_HOLDER.WEBVIEW_APK_FEATURES;
+ }
+
/**
* Utility method for throwing an exception explaining that the feature the app trying to use
* isn't supported.
diff --git a/webkit/src/main/java/androidx/webkit/internal/WebViewGlueCommunicator.java b/webkit/src/main/java/androidx/webkit/internal/WebViewGlueCommunicator.java
index 33ac145..9adffe7 100644
--- a/webkit/src/main/java/androidx/webkit/internal/WebViewGlueCommunicator.java
+++ b/webkit/src/main/java/androidx/webkit/internal/WebViewGlueCommunicator.java
@@ -39,49 +39,53 @@
/**
* Fetch the one global support library WebViewProviderFactory from the WebView glue layer.
*/
- public static WebViewProviderFactoryAdapter getFactory() {
+ public static WebViewProviderFactory getFactory() {
return LAZY_FACTORY_HOLDER.INSTANCE;
}
public static WebkitToCompatConverter getCompatConverter() {
- return LAZY_FACTORY_HOLDER.COMPAT_CONVERTER;
+ return LAZY_COMPAT_CONVERTER_HOLDER.INSTANCE;
}
private static class LAZY_FACTORY_HOLDER {
- static final WebViewProviderFactoryAdapter INSTANCE =
- new WebViewProviderFactoryAdapter(
- WebViewGlueCommunicator.createGlueProviderFactory());
- static final WebkitToCompatConverter COMPAT_CONVERTER =
- new WebkitToCompatConverter(
- INSTANCE.getWebkitToCompatConverter());
+ private static final WebViewProviderFactory INSTANCE =
+ WebViewGlueCommunicator.createGlueProviderFactory();
}
- private static InvocationHandler fetchGlueProviderFactoryImpl() {
+ private static class LAZY_COMPAT_CONVERTER_HOLDER {
+ static final WebkitToCompatConverter INSTANCE = new WebkitToCompatConverter(
+ WebViewGlueCommunicator.getFactory().getWebkitToCompatConverter());
+ }
+
+ private static InvocationHandler fetchGlueProviderFactoryImpl() throws IllegalAccessException,
+ InvocationTargetException, ClassNotFoundException, NoSuchMethodException {
+ Class<?> glueFactoryProviderFetcherClass = Class.forName(
+ GLUE_FACTORY_PROVIDER_FETCHER_CLASS, false, getWebViewClassLoader());
+ Method createProviderFactoryMethod = glueFactoryProviderFetcherClass.getDeclaredMethod(
+ GLUE_FACTORY_PROVIDER_FETCHER_METHOD);
+ return (InvocationHandler) createProviderFactoryMethod.invoke(null);
+ }
+
+ private static WebViewProviderFactory createGlueProviderFactory() {
+ InvocationHandler invocationHandler;
try {
- Class<?> glueFactoryProviderFetcherClass = Class.forName(
- GLUE_FACTORY_PROVIDER_FETCHER_CLASS, false, getWebViewClassLoader());
- Method createProviderFactoryMethod = glueFactoryProviderFetcherClass.getDeclaredMethod(
- GLUE_FACTORY_PROVIDER_FETCHER_METHOD, InvocationHandler.class);
- return (InvocationHandler) createProviderFactoryMethod.invoke(null,
- BoundaryInterfaceReflectionUtil.createInvocationHandlerFor(
- new SupportLibraryInfo()));
+ invocationHandler = fetchGlueProviderFactoryImpl();
+ // The only way we should fail to fetch the provider-factory is if the class we are
+ // calling into doesn't exist - any other kind of failure is unexpected and should cause
+ // a run-time exception.
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
- throw new RuntimeException(e);
+ // If WebView APK support library glue entry point doesn't exist then return a Provider
+ // factory that declares that there are no features available.
+ return new IncompatibleApkWebViewProviderFactory();
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
- // TODO(gsennton) if the above happens we should avoid throwing an exception! And probably
- // declare that the list of features supported by the WebView APK is empty.
- }
-
- private static WebViewProviderFactoryBoundaryInterface createGlueProviderFactory() {
- InvocationHandler invocationHandler = fetchGlueProviderFactoryImpl();
- return BoundaryInterfaceReflectionUtil.castToSuppLibClass(
- WebViewProviderFactoryBoundaryInterface.class, invocationHandler);
+ return new WebViewProviderFactoryAdapter(BoundaryInterfaceReflectionUtil.castToSuppLibClass(
+ WebViewProviderFactoryBoundaryInterface.class, invocationHandler));
}
/**
diff --git a/webkit/src/main/java/androidx/webkit/internal/WebViewProviderFactory.java b/webkit/src/main/java/androidx/webkit/internal/WebViewProviderFactory.java
new file mode 100644
index 0000000..5e4669a
--- /dev/null
+++ b/webkit/src/main/java/androidx/webkit/internal/WebViewProviderFactory.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2018 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 androidx.webkit.internal;
+
+import android.webkit.WebView;
+
+import org.chromium.support_lib_boundary.ServiceWorkerControllerBoundaryInterface;
+import org.chromium.support_lib_boundary.StaticsBoundaryInterface;
+import org.chromium.support_lib_boundary.WebViewProviderBoundaryInterface;
+import org.chromium.support_lib_boundary.WebkitToCompatConverterBoundaryInterface;
+
+/**
+ * Interface representing {@link android.webkit.WebViewProviderFactory}.
+ * On device with a compatible WebView APK this interface is implemented by a class defined in the
+ * WebView APK itself.
+ * On devices without a compatible WebView APK this interface is implemented by a stub class
+ * {@link androidx.webkit.internal.IncompatibleWebViewProviderFactory}.
+ */
+public interface WebViewProviderFactory {
+ /**
+ * Create a support library version of {@link android.webkit.WebViewProvider}.
+ */
+ WebViewProviderBoundaryInterface createWebView(WebView webview);
+
+ /**
+ * Create the boundary interface for {@link androidx.webkit.internal.WebkitToCompatConverter}
+ * which converts android.webkit classes into their corresponding support library classes.
+ */
+ WebkitToCompatConverterBoundaryInterface getWebkitToCompatConverter();
+
+ /**
+ * Fetch the boundary interface representing
+ * {@link android.webkit.WebViewFactoryProvider#Statics}.
+ */
+ StaticsBoundaryInterface getStatics();
+
+ /**
+ * Fetch the features supported by the current WebView APK.
+ */
+ String[] getWebViewFeatures();
+
+ /**
+ * Fetch the boundary interface representing {@link android.webkit.ServiceWorkerController}.
+ */
+ ServiceWorkerControllerBoundaryInterface getServiceWorkerController();
+}
diff --git a/webkit/src/main/java/androidx/webkit/internal/WebViewProviderFactoryAdapter.java b/webkit/src/main/java/androidx/webkit/internal/WebViewProviderFactoryAdapter.java
index efe0e64..43e5eae 100644
--- a/webkit/src/main/java/androidx/webkit/internal/WebViewProviderFactoryAdapter.java
+++ b/webkit/src/main/java/androidx/webkit/internal/WebViewProviderFactoryAdapter.java
@@ -29,7 +29,7 @@
* Adapter for WebViewProviderFactoryBoundaryInterface providing static WebView functionality
* similar to that provided by {@link android.webkit.WebViewFactoryProvider}.
*/
-public class WebViewProviderFactoryAdapter {
+public class WebViewProviderFactoryAdapter implements WebViewProviderFactory {
WebViewProviderFactoryBoundaryInterface mImpl;
public WebViewProviderFactoryAdapter(WebViewProviderFactoryBoundaryInterface impl) {
@@ -41,6 +41,7 @@
* {@link android.webkit.WebViewProvider} - the class used to implement
* {@link androidx.webkit.WebViewCompat}.
*/
+ @Override
public WebViewProviderBoundaryInterface createWebView(WebView webview) {
return BoundaryInterfaceReflectionUtil.castToSuppLibClass(
WebViewProviderBoundaryInterface.class, mImpl.createWebView(webview));
@@ -51,6 +52,7 @@
* {@link androidx.webkit.internal.WebkitToCompatConverter}, which converts android.webkit
* classes into their corresponding support library classes.
*/
+ @Override
public WebkitToCompatConverterBoundaryInterface getWebkitToCompatConverter() {
return BoundaryInterfaceReflectionUtil.castToSuppLibClass(
WebkitToCompatConverterBoundaryInterface.class, mImpl.getWebkitToCompatConverter());
@@ -60,6 +62,7 @@
* Adapter method for fetching the support library class representing
* {@link android.webkit.WebViewFactoryProvider#Statics}.
*/
+ @Override
public StaticsBoundaryInterface getStatics() {
return BoundaryInterfaceReflectionUtil.castToSuppLibClass(
StaticsBoundaryInterface.class, mImpl.getStatics());
@@ -68,6 +71,7 @@
/**
* Adapter method for fetching the features supported by the current WebView APK.
*/
+ @Override
public String[] getWebViewFeatures() {
return mImpl.getSupportedFeatures();
}
@@ -76,6 +80,7 @@
* Adapter method for fetching the support library class representing
* {@link android.webkit.ServiceWorkerController}.
*/
+ @Override
public ServiceWorkerControllerBoundaryInterface getServiceWorkerController() {
return BoundaryInterfaceReflectionUtil.castToSuppLibClass(
ServiceWorkerControllerBoundaryInterface.class, mImpl.getServiceWorkerController());