summaryrefslogtreecommitdiff
path: root/android/support
diff options
context:
space:
mode:
authorJustin Klaassen <justinklaassen@google.com>2017-10-24 19:50:40 -0400
committerJustin Klaassen <justinklaassen@google.com>2017-10-24 19:50:40 -0400
commit47ed54e5d312f899507d28d6e95ccc18a0de19fe (patch)
tree7a2d435c55c36fbc1d07e895bd0c68b18f84e12c /android/support
parent07f9f65561c2b81bcd189b895b31bb2ad0438d74 (diff)
downloadandroid-28-47ed54e5d312f899507d28d6e95ccc18a0de19fe.tar.gz
Import Android SDK Platform P [4413397]
/google/data/ro/projects/android/fetch_artifact \ --bid 4413397 \ --target sdk_phone_armv7-win_sdk \ sdk-repo-linux-sources-4413397.zip AndroidVersion.ApiLevel has been modified to appear as 28 Change-Id: I3cf1f7c36e61c090dcc7de7bcfa812ef2bf96c00
Diffstat (limited to 'android/support')
-rw-r--r--android/support/LibraryVersions.java8
-rw-r--r--android/support/car/drawer/CarDrawerActivity.java152
-rw-r--r--android/support/car/drawer/CarDrawerAdapter.java182
-rw-r--r--android/support/car/drawer/CarDrawerController.java306
-rw-r--r--android/support/car/drawer/DrawerItemClickListener.java29
-rw-r--r--android/support/car/drawer/DrawerItemViewHolder.java87
-rw-r--r--android/support/car/widget/PagedListView.java57
-rw-r--r--android/support/media/tv/BasePreviewProgram.java100
-rw-r--r--android/support/media/tv/BaseProgram.java23
-rw-r--r--android/support/media/tv/Program.java3
-rw-r--r--android/support/media/tv/TvContractCompat.java82
-rw-r--r--android/support/media/tv/WatchNextProgram.java27
-rw-r--r--android/support/mediacompat/testlib/IntentConstants.java9
-rw-r--r--android/support/mediacompat/testlib/MediaControllerConstants.java53
-rw-r--r--android/support/mediacompat/testlib/MediaSessionConstants.java59
-rw-r--r--android/support/transition/AutoTransition.java6
-rw-r--r--android/support/v17/leanback/widget/GridLayoutManager.java18
-rw-r--r--android/support/v4/content/res/ResourcesCompat.java4
-rw-r--r--android/support/v4/media/RatingCompat.java23
-rw-r--r--android/support/v4/media/RatingCompatKitkat.java67
-rw-r--r--android/support/v4/provider/FontsContractCompat.java3
-rw-r--r--android/support/v7/app/MediaRouteButton.java3
-rw-r--r--android/support/v7/app/MediaRouteChooserDialog.java6
-rw-r--r--android/support/v7/app/MediaRouteControllerDialog.java8
-rw-r--r--android/support/v7/app/MediaRouterThemeHelper.java110
-rw-r--r--android/support/v7/recyclerview/extensions/ListAdapterHelperTest.java164
-rw-r--r--android/support/v7/util/DiffUtil.java67
-rw-r--r--android/support/v7/widget/AppCompatTextHelper.java37
-rw-r--r--android/support/v7/widget/RecyclerView.java18
-rw-r--r--android/support/v7/widget/TintTypedArray.java5
-rw-r--r--android/support/wear/ambient/AmbientMode.java15
31 files changed, 1258 insertions, 473 deletions
diff --git a/android/support/LibraryVersions.java b/android/support/LibraryVersions.java
index a046d95e..2f5730a2 100644
--- a/android/support/LibraryVersions.java
+++ b/android/support/LibraryVersions.java
@@ -28,7 +28,7 @@ public class LibraryVersions {
/**
* Version code for flatfoot 1.0 projects (room, lifecycles)
*/
- private static final Version FLATFOOT_1_0_BATCH = new Version("1.0.0-beta2");
+ private static final Version FLATFOOT_1_0_BATCH = new Version("1.0.0-rc1");
/**
* Version code for Room
@@ -45,15 +45,17 @@ public class LibraryVersions {
*/
public static final Version PAGING = new Version("1.0.0-alpha3");
+ private static final Version LIFECYCLES = new Version("1.0.3");
+
/**
* Version code for Lifecycle libs that are required by the support library
*/
- public static final Version LIFECYCLES_CORE = new Version("1.0.2");
+ public static final Version LIFECYCLES_CORE = LIFECYCLES;
/**
* Version code for Lifecycle runtime libs that are required by the support library
*/
- public static final Version LIFECYCLES_RUNTIME = new Version("1.0.0");
+ public static final Version LIFECYCLES_RUNTIME = LIFECYCLES;
/**
* Version code for shared code of flatfoot
diff --git a/android/support/car/drawer/CarDrawerActivity.java b/android/support/car/drawer/CarDrawerActivity.java
new file mode 100644
index 00000000..7100218a
--- /dev/null
+++ b/android/support/car/drawer/CarDrawerActivity.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2017 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 android.support.car.drawer;
+
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.support.annotation.LayoutRes;
+import android.support.annotation.Nullable;
+import android.support.car.R;
+import android.support.v4.widget.DrawerLayout;
+import android.support.v7.app.ActionBarDrawerToggle;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.view.LayoutInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * Common base Activity for car apps that need to present a Drawer.
+ *
+ * <p>This Activity manages the overall layout. To use it, sub-classes need to:
+ *
+ * <ul>
+ * <li>Provide the root-items for the Drawer by implementing {@link #getRootAdapter()}.
+ * <li>Add their main content using {@link #setMainContent(int)} or {@link #setMainContent(View)}.
+ * They can also add fragments to the main-content container by obtaining its id using
+ * {@link #getContentContainerId()}
+ * </ul>
+ *
+ * <p>This class will take care of drawer toggling and display.
+ *
+ * <p>The rootAdapter can implement nested-navigation, in its click-handling, by passing the
+ * CarDrawerAdapter for the next level to
+ * {@link CarDrawerController#switchToAdapter(CarDrawerAdapter)}.
+ *
+ * <p>Any Activity's based on this class need to set their theme to CarDrawerActivityTheme or a
+ * derivative.
+ */
+public abstract class CarDrawerActivity extends AppCompatActivity {
+ private CarDrawerController mDrawerController;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.car_drawer_activity);
+
+ DrawerLayout drawerLayout = findViewById(R.id.drawer_layout);
+ ActionBarDrawerToggle drawerToggle = new ActionBarDrawerToggle(
+ this /* activity */,
+ drawerLayout, /* DrawerLayout object */
+ R.string.car_drawer_open,
+ R.string.car_drawer_close);
+
+ Toolbar toolbar = findViewById(R.id.car_toolbar);
+ setSupportActionBar(toolbar);
+
+ mDrawerController = new CarDrawerController(toolbar, drawerLayout, drawerToggle);
+ mDrawerController.setRootAdapter(getRootAdapter());
+
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportActionBar().setHomeButtonEnabled(true);
+ }
+
+ /**
+ * Returns the {@link CarDrawerController} that is responsible for handling events relating
+ * to the drawer in this Activity.
+ *
+ * @return The {@link CarDrawerController} linked to this Activity. This value will be
+ * {@code null} if this method is called before {@code onCreate()} has been called.
+ */
+ @Nullable
+ protected CarDrawerController getDrawerController() {
+ return mDrawerController;
+ }
+
+ @Override
+ protected void onPostCreate(Bundle savedInstanceState) {
+ super.onPostCreate(savedInstanceState);
+ mDrawerController.syncState();
+ }
+
+ /**
+ * @return Adapter for root content of the Drawer.
+ */
+ protected abstract CarDrawerAdapter getRootAdapter();
+
+ /**
+ * Set main content to display in this Activity. It will be added to R.id.content_frame in
+ * car_drawer_activity.xml. NOTE: Do not use {@link #setContentView(View)}.
+ *
+ * @param view View to display as main content.
+ */
+ public void setMainContent(View view) {
+ ViewGroup parent = findViewById(getContentContainerId());
+ parent.addView(view);
+ }
+
+ /**
+ * Set main content to display in this Activity. It will be added to R.id.content_frame in
+ * car_drawer_activity.xml. NOTE: Do not use {@link #setContentView(int)}.
+ *
+ * @param resourceId Layout to display as main content.
+ */
+ public void setMainContent(@LayoutRes int resourceId) {
+ ViewGroup parent = findViewById(getContentContainerId());
+ LayoutInflater inflater = getLayoutInflater();
+ inflater.inflate(resourceId, parent, true);
+ }
+
+ /**
+ * Get the id of the main content Container which is a FrameLayout. Subclasses can add their own
+ * content/fragments inside here.
+ *
+ * @return Id of FrameLayout where main content of the subclass Activity can be added.
+ */
+ protected int getContentContainerId() {
+ return R.id.content_frame;
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mDrawerController.closeDrawer();
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ mDrawerController.onConfigurationChanged(newConfig);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ return mDrawerController.onOptionsItemSelected(item) || super.onOptionsItemSelected(item);
+ }
+}
diff --git a/android/support/car/drawer/CarDrawerAdapter.java b/android/support/car/drawer/CarDrawerAdapter.java
new file mode 100644
index 00000000..b0fd965d
--- /dev/null
+++ b/android/support/car/drawer/CarDrawerAdapter.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2017 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 android.support.car.drawer;
+
+import android.content.Context;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.car.R;
+import android.support.car.widget.PagedListView;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * Base adapter for displaying items in the car navigation drawer, which uses a
+ * {@link PagedListView}.
+ *
+ * <p>Subclasses must set the title that will be displayed when displaying the contents of the
+ * drawer via {@link #setTitle(CharSequence)}. The title can be updated at any point later on. The
+ * title of the root adapter will also be the main title showed in the toolbar when the drawer is
+ * closed. See {@link CarDrawerController#setRootAdapter(CarDrawerAdapter)} for more information.
+ *
+ * <p>This class also takes care of implementing the PageListView.ItemCamp contract and subclasses
+ * should implement {@link #getActualItemCount()}.
+ */
+public abstract class CarDrawerAdapter extends RecyclerView.Adapter<DrawerItemViewHolder>
+ implements PagedListView.ItemCap, DrawerItemClickListener {
+ private final boolean mShowDisabledListOnEmpty;
+ private final Drawable mEmptyListDrawable;
+ private int mMaxItems = PagedListView.ItemCap.UNLIMITED;
+ private CharSequence mTitle;
+ private TitleChangeListener mTitleChangeListener;
+
+ /**
+ * Interface for a class that will be notified a new title has been set on this adapter.
+ */
+ interface TitleChangeListener {
+ /**
+ * Called when {@link #setTitle(CharSequence)} has been called and the title has been
+ * changed.
+ */
+ void onTitleChanged(CharSequence newTitle);
+ }
+
+ protected CarDrawerAdapter(Context context, boolean showDisabledListOnEmpty) {
+ mShowDisabledListOnEmpty = showDisabledListOnEmpty;
+
+ mEmptyListDrawable = context.getDrawable(R.drawable.ic_list_view_disable);
+ mEmptyListDrawable.setColorFilter(context.getColor(R.color.car_tint),
+ PorterDuff.Mode.SRC_IN);
+ }
+
+ /** Returns the title set via {@link #setTitle(CharSequence)}. */
+ CharSequence getTitle() {
+ return mTitle;
+ }
+
+ /** Updates the title to display in the toolbar for this Adapter. */
+ public final void setTitle(@NonNull CharSequence title) {
+ if (title == null) {
+ throw new IllegalArgumentException("setTitle() cannot be passed a null title!");
+ }
+
+ mTitle = title;
+
+ if (mTitleChangeListener != null) {
+ mTitleChangeListener.onTitleChanged(mTitle);
+ }
+ }
+
+ /** Sets a listener to be notified whenever the title of this adapter has been changed. */
+ void setTitleChangeListener(@Nullable TitleChangeListener listener) {
+ mTitleChangeListener = listener;
+ }
+
+ @Override
+ public final void setMaxItems(int maxItems) {
+ mMaxItems = maxItems;
+ }
+
+ @Override
+ public final int getItemCount() {
+ if (shouldShowDisabledListItem()) {
+ return 1;
+ }
+ return mMaxItems >= 0 ? Math.min(mMaxItems, getActualItemCount()) : getActualItemCount();
+ }
+
+ /**
+ * Returns the absolute number of items that can be displayed in the list.
+ *
+ * <p>A class should implement this method to supply the number of items to be displayed.
+ * Returning 0 from this method will cause an empty list icon to be displayed in the drawer.
+ *
+ * <p>A class should override this method rather than {@link #getItemCount()} because that
+ * method is handling the logic of when to display the empty list icon. It will return 1 when
+ * {@link #getActualItemCount()} returns 0.
+ *
+ * @return The number of items to be displayed in the list.
+ */
+ protected abstract int getActualItemCount();
+
+ @Override
+ public final int getItemViewType(int position) {
+ if (shouldShowDisabledListItem()) {
+ return R.layout.car_drawer_list_item_empty;
+ }
+
+ return usesSmallLayout(position)
+ ? R.layout.car_drawer_list_item_small
+ : R.layout.car_drawer_list_item_normal;
+ }
+
+ /**
+ * Used to indicate the layout used for the Drawer item at given position. Subclasses can
+ * override this to use normal layout which includes text element below title.
+ *
+ * <p>A small layout is presented by the layout {@code R.layout.car_drawer_list_item_small}.
+ * Otherwise, the layout {@code R.layout.car_drawer_list_item_normal} will be used.
+ *
+ * @param position Adapter position of item.
+ * @return Whether the item at this position will use a small layout (default) or normal layout.
+ */
+ protected boolean usesSmallLayout(int position) {
+ return true;
+ }
+
+ @Override
+ public final DrawerItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ View view = LayoutInflater.from(parent.getContext()).inflate(viewType, parent, false);
+ return new DrawerItemViewHolder(view);
+ }
+
+ @Override
+ public final void onBindViewHolder(DrawerItemViewHolder holder, int position) {
+ if (shouldShowDisabledListItem()) {
+ holder.getTitle().setText(null);
+ holder.getIcon().setImageDrawable(mEmptyListDrawable);
+ holder.setItemClickListener(null);
+ } else {
+ holder.setItemClickListener(this);
+ populateViewHolder(holder, position);
+ }
+ }
+
+ /**
+ * Whether or not this adapter should be displaying an empty list icon. The icon is shown if it
+ * has been configured to show and there are no items to be displayed.
+ */
+ private boolean shouldShowDisabledListItem() {
+ return mShowDisabledListOnEmpty && getActualItemCount() == 0;
+ }
+
+ /**
+ * Subclasses should set all elements in {@code holder} to populate the drawer-item. If some
+ * element is not used, it should be nulled out since these ViewHolder/View's are recycled.
+ */
+ protected abstract void populateViewHolder(DrawerItemViewHolder holder, int position);
+
+ /**
+ * Called when this adapter has been popped off the stack and is no longer needed. Subclasses
+ * can override to do any necessary cleanup.
+ */
+ public void cleanup() {}
+}
diff --git a/android/support/car/drawer/CarDrawerController.java b/android/support/car/drawer/CarDrawerController.java
new file mode 100644
index 00000000..4d9f4e99
--- /dev/null
+++ b/android/support/car/drawer/CarDrawerController.java
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2017 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 android.support.car.drawer;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.car.R;
+import android.support.car.widget.PagedListView;
+import android.support.v4.widget.DrawerLayout;
+import android.support.v7.app.ActionBarDrawerToggle;
+import android.support.v7.widget.Toolbar;
+import android.view.Gravity;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.ProgressBar;
+
+import java.util.Stack;
+
+/**
+ * A controller that will handle the set up of the navigation drawer. It will hook up the
+ * necessary buttons for up navigation, as well as expose methods to allow for a drill down
+ * navigation.
+ */
+public class CarDrawerController {
+ /** The amount that the drawer has been opened before its color should be switched. */
+ private static final float COLOR_SWITCH_SLIDE_OFFSET = 0.25f;
+
+ /**
+ * A representation of the hierarchy of navigation being displayed in the list. The ordering of
+ * this stack is the order that the user has visited each level. When the user navigates up,
+ * the adapters are poopped from this list.
+ */
+ private final Stack<CarDrawerAdapter> mAdapterStack = new Stack<>();
+
+ private final Context mContext;
+
+ private final Toolbar mToolbar;
+ private final DrawerLayout mDrawerLayout;
+ private final ActionBarDrawerToggle mDrawerToggle;
+
+ private final PagedListView mDrawerList;
+ private final ProgressBar mProgressBar;
+ private final View mDrawerContent;
+
+ /**
+ * Creates a {@link CarDrawerController} that will control the navigation of the drawer given by
+ * {@code drawerLayout}.
+ *
+ * <p>The given {@code drawerLayout} should either have a child View that is inflated from
+ * {@code R.layout.car_drawer} or ensure that it three children that have the IDs found in that
+ * layout.
+ *
+ * @param toolbar The {@link Toolbar} that will serve as the action bar for an Activity.
+ * @param drawerLayout The top-level container for the window content that shows the
+ * interactive drawer.
+ * @param drawerToggle The {@link ActionBarDrawerToggle} that bridges the given {@code toolbar}
+ * and {@code drawerLayout}.
+ */
+ public CarDrawerController(Toolbar toolbar,
+ DrawerLayout drawerLayout,
+ ActionBarDrawerToggle drawerToggle) {
+ mToolbar = toolbar;
+ mContext = drawerLayout.getContext();
+
+ mDrawerLayout = drawerLayout;
+
+ mDrawerContent = drawerLayout.findViewById(R.id.drawer_content);
+ mDrawerList = drawerLayout.findViewById(R.id.drawer_list);
+ mDrawerList.setMaxPages(PagedListView.ItemCap.UNLIMITED);
+
+ mProgressBar = drawerLayout.findViewById(R.id.drawer_progress);
+
+ mDrawerToggle = drawerToggle;
+ setupDrawerToggling();
+ }
+
+ /**
+ * Sets the {@link CarDrawerAdapter} that will function as the root adapter. The contents of
+ * this root adapter are shown when the drawer is first opened. It is also the top-most level of
+ * navigation in the drawer.
+ *
+ * @param rootAdapter The adapter that will act as the root. If this value is {@code null}, then
+ * this method will do nothing.
+ */
+ public void setRootAdapter(@Nullable CarDrawerAdapter rootAdapter) {
+ if (rootAdapter == null) {
+ return;
+ }
+
+ mAdapterStack.push(rootAdapter);
+ setToolbarTitleFrom(rootAdapter);
+ mDrawerList.setAdapter(rootAdapter);
+ }
+
+ /**
+ * Switches to use the given {@link CarDrawerAdapter} as the one to supply the list to display
+ * in the navigation drawer. The title will also be updated from the adapter.
+ *
+ * <p>This switch is treated as a navigation to the next level in the drawer. Navigation away
+ * from this level will pop the given adapter off and surface contents of the previous adapter
+ * that was set via this method. If no such adapter exists, then the root adapter set by
+ * {@link #setRootAdapter(CarDrawerAdapter)} will be used instead.
+ *
+ * @param adapter Adapter for next level of content in the drawer.
+ */
+ public final void switchToAdapter(CarDrawerAdapter adapter) {
+ mAdapterStack.peek().setTitleChangeListener(null);
+ mAdapterStack.push(adapter);
+ switchToAdapterInternal(adapter);
+ }
+
+ /** Close the drawer. */
+ public void closeDrawer() {
+ if (mDrawerLayout.isDrawerOpen(Gravity.LEFT)) {
+ mDrawerLayout.closeDrawer(Gravity.LEFT);
+ }
+ }
+
+ /** Opens the drawer. */
+ public void openDrawer() {
+ if (!mDrawerLayout.isDrawerOpen(Gravity.LEFT)) {
+ mDrawerLayout.openDrawer(Gravity.LEFT);
+ }
+ }
+
+ /** Sets a listener to be notified of Drawer events. */
+ public void addDrawerListener(@NonNull DrawerLayout.DrawerListener listener) {
+ mDrawerLayout.addDrawerListener(listener);
+ }
+
+ /** Removes a listener to be notified of Drawer events. */
+ public void removeDrawerListener(@NonNull DrawerLayout.DrawerListener listener) {
+ mDrawerLayout.removeDrawerListener(listener);
+ }
+
+ /**
+ * Sets whether the loading progress bar is displayed in the navigation drawer. If {@code true},
+ * the progress bar is displayed and the navigation list is hidden and vice versa.
+ */
+ public void showLoadingProgressBar(boolean show) {
+ mDrawerList.setVisibility(show ? View.INVISIBLE : View.VISIBLE);
+ mProgressBar.setVisibility(show ? View.VISIBLE : View.GONE);
+ }
+
+ /** Scroll to given position in the list. */
+ public void scrollToPosition(int position) {
+ mDrawerList.getRecyclerView().smoothScrollToPosition(position);
+ }
+
+ /**
+ * Retrieves the title from the given {@link CarDrawerAdapter} and set its as the title of this
+ * controller's internal Toolbar.
+ */
+ private void setToolbarTitleFrom(CarDrawerAdapter adapter) {
+ if (adapter.getTitle() == null) {
+ throw new RuntimeException("CarDrawerAdapter must supply a title via setTitle()");
+ }
+
+ mToolbar.setTitle(adapter.getTitle());
+ adapter.setTitleChangeListener(mToolbar::setTitle);
+ }
+
+ /**
+ * Sets up the necessary listeners for {@link DrawerLayout} so that the navigation drawer
+ * hierarchy is properly displayed.
+ */
+ private void setupDrawerToggling() {
+ mDrawerLayout.addDrawerListener(mDrawerToggle);
+ mDrawerLayout.addDrawerListener(
+ new DrawerLayout.DrawerListener() {
+ @Override
+ public void onDrawerSlide(View drawerView, float slideOffset) {
+ // Correctly set the title and arrow colors as they are different between
+ // the open and close states.
+ updateTitleAndArrowColor(slideOffset >= COLOR_SWITCH_SLIDE_OFFSET);
+ }
+
+ @Override
+ public void onDrawerClosed(View drawerView) {
+ // If drawer is closed, revert stack/drawer to initial root state.
+ cleanupStackAndShowRoot();
+ scrollToPosition(0);
+ }
+
+ @Override
+ public void onDrawerOpened(View drawerView) {}
+
+ @Override
+ public void onDrawerStateChanged(int newState) {}
+ });
+ }
+
+ /** Sets the title and arrow color of the drawer depending on if it is open or not. */
+ private void updateTitleAndArrowColor(boolean drawerOpen) {
+ // When the drawer is open, use car_title, which resolves to appropriate color depending on
+ // day-night mode. When drawer is closed, we always use light color.
+ int titleColorResId = drawerOpen ? R.color.car_title : R.color.car_title_light;
+ int titleColor = mContext.getColor(titleColorResId);
+ mToolbar.setTitleTextColor(titleColor);
+ mDrawerToggle.getDrawerArrowDrawable().setColor(titleColor);
+ }
+
+ /**
+ * Synchronizes the display of the drawer with its linked {@link DrawerLayout}.
+ *
+ * <p>This should be called from the associated Activity's
+ * {@link android.support.v7.app.AppCompatActivity#onPostCreate(Bundle)} method to synchronize
+ * after teh DRawerLayout's instance state has been restored, and any other time when the
+ * state may have diverged in such a way that this controller's associated
+ * {@link ActionBarDrawerToggle} had not been notified.
+ */
+ public void syncState() {
+ mDrawerToggle.syncState();
+
+ // In case we're restarting after a config change (e.g. day, night switch), set colors
+ // again. Doing it here so that Drawer state is fully synced and we know if its open or not.
+ // NOTE: isDrawerOpen must be passed the second child of the DrawerLayout.
+ updateTitleAndArrowColor(mDrawerLayout.isDrawerOpen(mDrawerContent));
+ }
+
+ /**
+ * Notify this controller that device configurations may have changed.
+ *
+ * <p>This method should be called from the associated Activity's
+ * {@code onConfigurationChanged()} method.
+ */
+ public void onConfigurationChanged(Configuration newConfig) {
+ // Pass any configuration change to the drawer toggle.
+ mDrawerToggle.onConfigurationChanged(newConfig);
+ }
+
+ /**
+ * An analog to an Activity's {@code onOptionsItemSelected()}. This method should be called
+ * when the Activity's method is called and will return {@code true} if the selection has
+ * been handled.
+ *
+ * @return {@code true} if the item processing was handled by this class.
+ */
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // Handle home-click and see if we can navigate up in the drawer.
+ if (item != null && item.getItemId() == android.R.id.home && maybeHandleUpClick()) {
+ return true;
+ }
+
+ // DrawerToggle gets next chance to handle up-clicks (and any other clicks).
+ return mDrawerToggle.onOptionsItemSelected(item);
+ }
+
+ /**
+ * Sets the navigation drawer's title to be the one supplied by the given adapter and updates
+ * the navigation drawer list with the adapter's contents.
+ */
+ private void switchToAdapterInternal(CarDrawerAdapter adapter) {
+ setToolbarTitleFrom(adapter);
+ // NOTE: We don't use swapAdapter() since different levels in the Drawer may switch between
+ // car_drawer_list_item_normal, car_drawer_list_item_small and car_list_empty layouts.
+ mDrawerList.getRecyclerView().setAdapter(adapter);
+ scrollToPosition(0);
+ }
+
+ /**
+ * Switches to the previous level in the drawer hierarchy if the current list being displayed
+ * is not the root adapter. This is analogous to a navigate up.
+ *
+ * @return {@code true} if a navigate up was possible and executed. {@code false} otherwise.
+ */
+ private boolean maybeHandleUpClick() {
+ // Check if already at the root level.
+ if (mAdapterStack.size() <= 1) {
+ return false;
+ }
+
+ CarDrawerAdapter adapter = mAdapterStack.pop();
+ adapter.setTitleChangeListener(null);
+ adapter.cleanup();
+ switchToAdapterInternal(mAdapterStack.peek());
+ return true;
+ }
+
+ /** Clears stack down to root adapter and switches to root adapter. */
+ private void cleanupStackAndShowRoot() {
+ while (mAdapterStack.size() > 1) {
+ CarDrawerAdapter adapter = mAdapterStack.pop();
+ adapter.setTitleChangeListener(null);
+ adapter.cleanup();
+ }
+ switchToAdapterInternal(mAdapterStack.peek());
+ }
+}
diff --git a/android/support/car/drawer/DrawerItemClickListener.java b/android/support/car/drawer/DrawerItemClickListener.java
new file mode 100644
index 00000000..d707dbd0
--- /dev/null
+++ b/android/support/car/drawer/DrawerItemClickListener.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2017 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 android.support.car.drawer;
+
+/**
+ * Listener for handling clicks on items/views managed by {@link DrawerItemViewHolder}.
+ */
+public interface DrawerItemClickListener {
+ /**
+ * Callback when item is clicked.
+ *
+ * @param position Adapter position of the clicked item.
+ */
+ void onItemClick(int position);
+}
diff --git a/android/support/car/drawer/DrawerItemViewHolder.java b/android/support/car/drawer/DrawerItemViewHolder.java
new file mode 100644
index 00000000..d016b2de
--- /dev/null
+++ b/android/support/car/drawer/DrawerItemViewHolder.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2017 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 android.support.car.drawer;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.car.R;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+/**
+ * Re-usable {@link RecyclerView.ViewHolder} for displaying items in the
+ * {@link android.support.car.drawer.CarDrawerAdapter}.
+ */
+public class DrawerItemViewHolder extends RecyclerView.ViewHolder {
+ private final ImageView mIcon;
+ private final TextView mTitle;
+ private final TextView mText;
+ private final ImageView mEndIcon;
+
+ DrawerItemViewHolder(View view) {
+ super(view);
+ mIcon = view.findViewById(R.id.icon);
+ if (mIcon == null) {
+ throw new IllegalArgumentException("Icon view cannot be null!");
+ }
+
+ mTitle = view.findViewById(R.id.title);
+ if (mTitle == null) {
+ throw new IllegalArgumentException("Title view cannot be null!");
+ }
+
+ // Next two are optional and may be null.
+ mText = view.findViewById(R.id.text);
+ mEndIcon = view.findViewById(R.id.end_icon);
+ }
+
+ /** Returns the view that should be used to display the main icon. */
+ @NonNull
+ public ImageView getIcon() {
+ return mIcon;
+ }
+
+ /** Returns the view that will display the main title. */
+ @NonNull
+ public TextView getTitle() {
+ return mTitle;
+ }
+
+ /** Returns the view that is used for text that is smaller than the title text. */
+ @Nullable
+ public TextView getText() {
+ return mText;
+ }
+
+ /** Returns the icon that is displayed at the end of the view. */
+ @Nullable
+ public ImageView getEndIcon() {
+ return mEndIcon;
+ }
+
+ /**
+ * Sets the listener that will be notified when the view held by this ViewHolder has been
+ * clicked. Passing {@code null} will clear any previously set listeners.
+ */
+ void setItemClickListener(@Nullable DrawerItemClickListener listener) {
+ itemView.setOnClickListener(listener != null
+ ? v -> listener.onItemClick(getAdapterPosition())
+ : null);
+ }
+}
diff --git a/android/support/car/widget/PagedListView.java b/android/support/car/widget/PagedListView.java
index 8527c659..46527001 100644
--- a/android/support/car/widget/PagedListView.java
+++ b/android/support/car/widget/PagedListView.java
@@ -27,7 +27,6 @@ import android.os.Handler;
import android.support.annotation.IdRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
-import android.support.annotation.Px;
import android.support.annotation.RestrictTo;
import android.support.annotation.UiThread;
import android.support.car.R;
@@ -61,7 +60,6 @@ public class PagedListView extends FrameLayout {
protected final CarLayoutManager mLayoutManager;
protected final Handler mHandler = new Handler();
private final boolean mScrollBarEnabled;
- private final boolean mRightGutterEnabled;
private final PagedScrollBarView mScrollBarView;
private int mRowsPerPage = -1;
@@ -98,6 +96,11 @@ public class PagedListView extends FrameLayout {
*/
public interface ItemCap {
/**
+ * A value to pass to {@link #setMaxItems(int)} that indicates there should be no limit.
+ */
+ int UNLIMITED = -1;
+
+ /**
* Sets the maximum number of items available in the adapter. A value less than '0' means
* the list should not be capped.
*/
@@ -139,7 +142,6 @@ public class PagedListView extends FrameLayout {
}
LayoutInflater.from(context).inflate(layoutId, this /*root*/, true /*attachToRoot*/);
- FrameLayout maxWidthLayout = (FrameLayout) findViewById(R.id.recycler_view_container);
TypedArray a = context.obtainStyledAttributes(
attrs, R.styleable.PagedListView, defStyleAttrs, defStyleRes);
mRecyclerView = (CarRecyclerView) findViewById(R.id.recycler_view);
@@ -156,6 +158,16 @@ public class PagedListView extends FrameLayout {
mRecyclerView.getRecycledViewPool().setMaxRecycledViews(0, 12);
mRecyclerView.setItemAnimator(new CarItemAnimator(mLayoutManager));
+ boolean offsetScrollBar = a.getBoolean(R.styleable.PagedListView_offsetScrollBar, false);
+ if (offsetScrollBar) {
+ MarginLayoutParams params = (MarginLayoutParams) mRecyclerView.getLayoutParams();
+ params.setMarginStart(getResources().getDimensionPixelSize(
+ R.dimen.car_screen_margin_size));
+ params.setMarginEnd(
+ a.getDimensionPixelSize(R.styleable.PagedListView_listEndMargin, 0));
+ mRecyclerView.setLayoutParams(params);
+ }
+
if (a.getBoolean(R.styleable.PagedListView_showPagedListViewDivider, true)) {
int dividerStartMargin = a.getDimensionPixelSize(
R.styleable.PagedListView_dividerStartMargin, 0);
@@ -199,47 +211,20 @@ public class PagedListView extends FrameLayout {
}
}
});
+
mScrollBarView.setVisibility(mScrollBarEnabled ? VISIBLE : GONE);
- // Modify the layout if the Gutter or the Scroll Bar are not visible.
- mRightGutterEnabled = a.getBoolean(R.styleable.PagedListView_rightGutterEnabled, false);
- if (mRightGutterEnabled || !mScrollBarEnabled) {
- FrameLayout.LayoutParams maxWidthLayoutLayoutParams =
- (FrameLayout.LayoutParams) maxWidthLayout.getLayoutParams();
- if (mRightGutterEnabled) {
- maxWidthLayoutLayoutParams.rightMargin =
- getResources().getDimensionPixelSize(R.dimen.car_card_margin);
- }
- if (!mScrollBarEnabled) {
- maxWidthLayoutLayoutParams.setMarginStart(0);
- }
- maxWidthLayout.setLayoutParams(maxWidthLayoutLayoutParams);
+ // Modify the layout the Scroll Bar is not visible.
+ if (!mScrollBarEnabled) {
+ MarginLayoutParams params = (MarginLayoutParams) mRecyclerView.getLayoutParams();
+ params.setMarginStart(0);
+ mRecyclerView.setLayoutParams(params);
}
setDayNightStyle(DayNightStyle.AUTO);
a.recycle();
}
- /**
- * Sets the starting and ending padding for each view in the list.
- *
- * @param start The start padding.
- * @param end The end padding.
- */
- public void setListViewStartEndPadding(@Px int start, @Px int end) {
- int carCardMargin = getResources().getDimensionPixelSize(R.dimen.car_card_margin);
- int startGutter = mScrollBarEnabled ? carCardMargin : 0;
- int startPadding = Math.max(start - startGutter, 0);
- int endGutter = mRightGutterEnabled ? carCardMargin : 0;
- int endPadding = Math.max(end - endGutter, 0);
- mRecyclerView.setPaddingRelative(startPadding, mRecyclerView.getPaddingTop(),
- endPadding, mRecyclerView.getPaddingBottom());
-
- // Since we're setting padding we'll need to set the clip to padding to the same
- // value as clip children to ensure that the cards fly off the screen.
- mRecyclerView.setClipToPadding(mRecyclerView.getClipChildren());
- }
-
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
diff --git a/android/support/media/tv/BasePreviewProgram.java b/android/support/media/tv/BasePreviewProgram.java
index 1423d9d6..39c30140 100644
--- a/android/support/media/tv/BasePreviewProgram.java
+++ b/android/support/media/tv/BasePreviewProgram.java
@@ -23,14 +23,13 @@ import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
+import android.support.annotation.IntDef;
import android.support.annotation.RestrictTo;
import android.support.media.tv.TvContractCompat.PreviewProgramColumns;
-import android.support.media.tv.TvContractCompat.PreviewProgramColumns.AspectRatio;
-import android.support.media.tv.TvContractCompat.PreviewProgramColumns.Availability;
-import android.support.media.tv.TvContractCompat.PreviewProgramColumns.InteractionType;
-import android.support.media.tv.TvContractCompat.PreviewProgramColumns.Type;
import android.support.media.tv.TvContractCompat.PreviewPrograms;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.Date;
@@ -55,6 +54,89 @@ public abstract class BasePreviewProgram extends BaseProgram {
private static final int IS_LIVE = 1;
private static final int IS_BROWSABLE = 1;
+ /** @hide */
+ @IntDef({
+ TYPE_UNKNOWN,
+ PreviewProgramColumns.TYPE_MOVIE,
+ PreviewProgramColumns.TYPE_TV_SERIES,
+ PreviewProgramColumns.TYPE_TV_SEASON,
+ PreviewProgramColumns.TYPE_TV_EPISODE,
+ PreviewProgramColumns.TYPE_CLIP,
+ PreviewProgramColumns.TYPE_EVENT,
+ PreviewProgramColumns.TYPE_CHANNEL,
+ PreviewProgramColumns.TYPE_TRACK,
+ PreviewProgramColumns.TYPE_ALBUM,
+ PreviewProgramColumns.TYPE_ARTIST,
+ PreviewProgramColumns.TYPE_PLAYLIST,
+ PreviewProgramColumns.TYPE_STATION,
+ PreviewProgramColumns.TYPE_GAME
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @RestrictTo(LIBRARY_GROUP)
+ public @interface Type {}
+
+ /**
+ * The unknown program type.
+ */
+ private static final int TYPE_UNKNOWN = -1;
+
+ /** @hide */
+ @IntDef({
+ ASPECT_RATIO_UNKNOWN,
+ PreviewProgramColumns.ASPECT_RATIO_16_9,
+ PreviewProgramColumns.ASPECT_RATIO_3_2,
+ PreviewProgramColumns.ASPECT_RATIO_4_3,
+ PreviewProgramColumns.ASPECT_RATIO_1_1,
+ PreviewProgramColumns.ASPECT_RATIO_2_3,
+ PreviewProgramColumns.ASPECT_RATIO_MOVIE_POSTER
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @RestrictTo(LIBRARY_GROUP)
+ public @interface AspectRatio {}
+
+ /**
+ * The aspect ratio for unknown aspect ratios.
+ */
+ private static final int ASPECT_RATIO_UNKNOWN = -1;
+
+ /** @hide */
+ @IntDef({
+ AVAILABILITY_UNKNOWN,
+ PreviewProgramColumns.AVAILABILITY_AVAILABLE,
+ PreviewProgramColumns.AVAILABILITY_FREE_WITH_SUBSCRIPTION,
+ PreviewProgramColumns.AVAILABILITY_PAID_CONTENT,
+ PreviewProgramColumns.AVAILABILITY_PURCHASED,
+ PreviewProgramColumns.AVAILABILITY_FREE
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @RestrictTo(LIBRARY_GROUP)
+ public @interface Availability {}
+
+ /**
+ * The unknown availability.
+ */
+ private static final int AVAILABILITY_UNKNOWN = -1;
+
+ /** @hide */
+ @IntDef({
+ INTERACTION_TYPE_UNKNOWN,
+ PreviewProgramColumns.INTERACTION_TYPE_VIEWS,
+ PreviewProgramColumns.INTERACTION_TYPE_LISTENS,
+ PreviewProgramColumns.INTERACTION_TYPE_FOLLOWERS,
+ PreviewProgramColumns.INTERACTION_TYPE_FANS,
+ PreviewProgramColumns.INTERACTION_TYPE_LIKES,
+ PreviewProgramColumns.INTERACTION_TYPE_THUMBS,
+ PreviewProgramColumns.INTERACTION_TYPE_VIEWERS,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @RestrictTo(LIBRARY_GROUP)
+ public @interface InteractionType {}
+
+ /**
+ * The unknown interaction type.
+ */
+ private static final int INTERACTION_TYPE_UNKNOWN = -1;
+
BasePreviewProgram(Builder builder) {
super(builder);
}
@@ -127,7 +209,7 @@ public abstract class BasePreviewProgram extends BaseProgram {
*/
public @Type int getType() {
Integer i = mValues.getAsInteger(PreviewPrograms.COLUMN_TYPE);
- return i == null ? INVALID_INT_VALUE : i;
+ return i == null ? TYPE_UNKNOWN : i;
}
/**
@@ -137,7 +219,7 @@ public abstract class BasePreviewProgram extends BaseProgram {
*/
public @AspectRatio int getPosterArtAspectRatio() {
Integer i = mValues.getAsInteger(PreviewPrograms.COLUMN_POSTER_ART_ASPECT_RATIO);
- return i == null ? INVALID_INT_VALUE : i;
+ return i == null ? ASPECT_RATIO_UNKNOWN : i;
}
/**
@@ -147,7 +229,7 @@ public abstract class BasePreviewProgram extends BaseProgram {
*/
public @AspectRatio int getThumbnailAspectRatio() {
Integer i = mValues.getAsInteger(PreviewPrograms.COLUMN_THUMBNAIL_ASPECT_RATIO);
- return i == null ? INVALID_INT_VALUE : i;
+ return i == null ? ASPECT_RATIO_UNKNOWN : i;
}
/**
@@ -165,7 +247,7 @@ public abstract class BasePreviewProgram extends BaseProgram {
*/
public @Availability int getAvailability() {
Integer i = mValues.getAsInteger(PreviewPrograms.COLUMN_AVAILABILITY);
- return i == null ? INVALID_INT_VALUE : i;
+ return i == null ? AVAILABILITY_UNKNOWN : i;
}
/**
@@ -216,7 +298,7 @@ public abstract class BasePreviewProgram extends BaseProgram {
*/
public @InteractionType int getInteractionType() {
Integer i = mValues.getAsInteger(PreviewPrograms.COLUMN_INTERACTION_TYPE);
- return i == null ? INVALID_INT_VALUE : i;
+ return i == null ? INTERACTION_TYPE_UNKNOWN : i;
}
/**
diff --git a/android/support/media/tv/BaseProgram.java b/android/support/media/tv/BaseProgram.java
index e4ce9d1f..23b5cf9c 100644
--- a/android/support/media/tv/BaseProgram.java
+++ b/android/support/media/tv/BaseProgram.java
@@ -22,13 +22,16 @@ import android.database.Cursor;
import android.media.tv.TvContentRating;
import android.net.Uri;
import android.os.Build;
+import android.support.annotation.IntDef;
import android.support.annotation.RestrictTo;
import android.support.media.tv.TvContractCompat.BaseTvColumns;
import android.support.media.tv.TvContractCompat.ProgramColumns;
-import android.support.media.tv.TvContractCompat.ProgramColumns.ReviewRatingStyle;
import android.support.media.tv.TvContractCompat.Programs;
import android.support.media.tv.TvContractCompat.Programs.Genres.Genre;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* Base class for derived classes that want to have common fields for programs defined in
* {@link TvContractCompat}.
@@ -46,6 +49,22 @@ public abstract class BaseProgram {
private static final int IS_SEARCHABLE = 1;
/** @hide */
+ @IntDef({
+ REVIEW_RATING_STYLE_UNKNOWN,
+ ProgramColumns.REVIEW_RATING_STYLE_STARS,
+ ProgramColumns.REVIEW_RATING_STYLE_THUMBS_UP_DOWN,
+ ProgramColumns.REVIEW_RATING_STYLE_PERCENTAGE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @RestrictTo(LIBRARY_GROUP)
+ @interface ReviewRatingStyle {}
+
+ /**
+ * The unknown review rating style.
+ */
+ private static final int REVIEW_RATING_STYLE_UNKNOWN = -1;
+
+ /** @hide */
@RestrictTo(LIBRARY_GROUP)
protected ContentValues mValues;
@@ -254,7 +273,7 @@ public abstract class BaseProgram {
*/
public @ReviewRatingStyle int getReviewRatingStyle() {
Integer i = mValues.getAsInteger(Programs.COLUMN_REVIEW_RATING_STYLE);
- return i == null ? INVALID_INT_VALUE : i;
+ return i == null ? REVIEW_RATING_STYLE_UNKNOWN : i;
}
/**
diff --git a/android/support/media/tv/Program.java b/android/support/media/tv/Program.java
index 4e3bd7ac..233f1bab 100644
--- a/android/support/media/tv/Program.java
+++ b/android/support/media/tv/Program.java
@@ -25,6 +25,7 @@ import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.RestrictTo;
import android.support.media.tv.TvContractCompat.Programs;
+import android.support.media.tv.TvContractCompat.Programs.Genres.Genre;
/**
* A convenience class to access {@link TvContractCompat.Programs} entries in the system content
@@ -282,7 +283,7 @@ public final class Program extends BaseProgram implements Comparable<Program> {
* @return This Builder object to allow for chaining of calls to builder methods.
* @see Programs#COLUMN_BROADCAST_GENRE
*/
- public Builder setBroadcastGenres(String[] genres) {
+ public Builder setBroadcastGenres(@Genre String[] genres) {
mValues.put(Programs.COLUMN_BROADCAST_GENRE, Programs.Genres.encode(genres));
return this;
}
diff --git a/android/support/media/tv/TvContractCompat.java b/android/support/media/tv/TvContractCompat.java
index 5a46e791..de4fd04f 100644
--- a/android/support/media/tv/TvContractCompat.java
+++ b/android/support/media/tv/TvContractCompat.java
@@ -30,7 +30,6 @@ import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.BaseColumns;
-import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
@@ -606,16 +605,6 @@ public final class TvContractCompat {
*/
@RestrictTo(LIBRARY_GROUP)
interface ProgramColumns {
- /** @hide */
- @IntDef({
- REVIEW_RATING_STYLE_STARS,
- REVIEW_RATING_STYLE_THUMBS_UP_DOWN,
- REVIEW_RATING_STYLE_PERCENTAGE,
- })
- @Retention(RetentionPolicy.SOURCE)
- @RestrictTo(LIBRARY_GROUP)
- @interface ReviewRatingStyle {}
-
/**
* The review rating style for five star rating.
*
@@ -934,27 +923,6 @@ public final class TvContractCompat {
*/
@RestrictTo(LIBRARY_GROUP)
public interface PreviewProgramColumns {
-
- /** @hide */
- @IntDef({
- TYPE_MOVIE,
- TYPE_TV_SERIES,
- TYPE_TV_SEASON,
- TYPE_TV_EPISODE,
- TYPE_CLIP,
- TYPE_EVENT,
- TYPE_CHANNEL,
- TYPE_TRACK,
- TYPE_ALBUM,
- TYPE_ARTIST,
- TYPE_PLAYLIST,
- TYPE_STATION,
- TYPE_GAME
- })
- @Retention(RetentionPolicy.SOURCE)
- @RestrictTo(LIBRARY_GROUP)
- public @interface Type {}
-
/**
* The program type for movie.
*
@@ -1046,19 +1014,6 @@ public final class TvContractCompat {
*/
int TYPE_GAME = 12;
- /** @hide */
- @IntDef({
- ASPECT_RATIO_16_9,
- ASPECT_RATIO_3_2,
- ASPECT_RATIO_4_3,
- ASPECT_RATIO_1_1,
- ASPECT_RATIO_2_3,
- ASPECT_RATIO_MOVIE_POSTER,
- })
- @Retention(RetentionPolicy.SOURCE)
- @RestrictTo(LIBRARY_GROUP)
- public @interface AspectRatio {}
-
/**
* The aspect ratio for 16:9.
*
@@ -1107,18 +1062,6 @@ public final class TvContractCompat {
*/
int ASPECT_RATIO_MOVIE_POSTER = 5;
- /** @hide */
- @IntDef({
- AVAILABILITY_AVAILABLE,
- AVAILABILITY_FREE_WITH_SUBSCRIPTION,
- AVAILABILITY_PAID_CONTENT,
- AVAILABILITY_PURCHASED,
- AVAILABILITY_FREE,
- })
- @Retention(RetentionPolicy.SOURCE)
- @RestrictTo(LIBRARY_GROUP)
- public @interface Availability {}
-
/**
* The availability for "available to this user".
*
@@ -1155,20 +1098,6 @@ public final class TvContractCompat {
*/
int AVAILABILITY_FREE = 4;
- /** @hide */
- @IntDef({
- INTERACTION_TYPE_VIEWS,
- INTERACTION_TYPE_LISTENS,
- INTERACTION_TYPE_FOLLOWERS,
- INTERACTION_TYPE_FANS,
- INTERACTION_TYPE_LIKES,
- INTERACTION_TYPE_THUMBS,
- INTERACTION_TYPE_VIEWERS,
- })
- @Retention(RetentionPolicy.SOURCE)
- @RestrictTo(LIBRARY_GROUP)
- public @interface InteractionType {}
-
/**
* The interaction type for "views".
*
@@ -2895,17 +2824,6 @@ public final class TvContractCompat {
/** The MIME type of a single preview TV program. */
public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/watch_next_program";
- /** @hide */
- @IntDef({
- WATCH_NEXT_TYPE_CONTINUE,
- WATCH_NEXT_TYPE_NEXT,
- WATCH_NEXT_TYPE_NEW,
- WATCH_NEXT_TYPE_WATCHLIST,
- })
- @Retention(RetentionPolicy.SOURCE)
- @RestrictTo(LIBRARY_GROUP)
- public @interface WatchNextType {}
-
/**
* The watch next type for CONTINUE. Use this type when the user has already watched more
* than 1 minute of this content.
diff --git a/android/support/media/tv/WatchNextProgram.java b/android/support/media/tv/WatchNextProgram.java
index f4665846..c192745c 100644
--- a/android/support/media/tv/WatchNextProgram.java
+++ b/android/support/media/tv/WatchNextProgram.java
@@ -22,12 +22,15 @@ import android.content.ContentValues;
import android.database.Cursor;
import android.media.tv.TvContentRating; // For javadoc gen of super class
import android.os.Build;
+import android.support.annotation.IntDef;
import android.support.annotation.RestrictTo;
import android.support.media.tv.TvContractCompat.PreviewPrograms; // For javadoc gen of super class
import android.support.media.tv.TvContractCompat.Programs; // For javadoc gen of super class
import android.support.media.tv.TvContractCompat.Programs.Genres; // For javadoc gen of super class
import android.support.media.tv.TvContractCompat.WatchNextPrograms;
-import android.support.media.tv.TvContractCompat.WatchNextPrograms.WatchNextType;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
/**
* A convenience class to access {@link WatchNextPrograms} entries in the system content
@@ -87,16 +90,34 @@ public final class WatchNextProgram extends BasePreviewProgram {
private static final long INVALID_LONG_VALUE = -1;
private static final int INVALID_INT_VALUE = -1;
+ /** @hide */
+ @IntDef({
+ WATCH_NEXT_TYPE_UNKNOWN,
+ WatchNextPrograms.WATCH_NEXT_TYPE_CONTINUE,
+ WatchNextPrograms.WATCH_NEXT_TYPE_NEXT,
+ WatchNextPrograms.WATCH_NEXT_TYPE_NEW,
+ WatchNextPrograms.WATCH_NEXT_TYPE_WATCHLIST,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @RestrictTo(LIBRARY_GROUP)
+ public @interface WatchNextType {}
+
+ /**
+ * The unknown watch next type. Use this type when the actual type is not known.
+ */
+ public static final int WATCH_NEXT_TYPE_UNKNOWN = -1;
+
private WatchNextProgram(Builder builder) {
super(builder);
}
/**
- * @return The value of {@link WatchNextPrograms#COLUMN_WATCH_NEXT_TYPE} for the program.
+ * @return The value of {@link WatchNextPrograms#COLUMN_WATCH_NEXT_TYPE} for the program,
+ * or {@link #WATCH_NEXT_TYPE_UNKNOWN} if it's unknown.
*/
public @WatchNextType int getWatchNextType() {
Integer i = mValues.getAsInteger(WatchNextPrograms.COLUMN_WATCH_NEXT_TYPE);
- return i == null ? INVALID_INT_VALUE : i;
+ return i == null ? WATCH_NEXT_TYPE_UNKNOWN : i;
}
/**
diff --git a/android/support/mediacompat/testlib/IntentConstants.java b/android/support/mediacompat/testlib/IntentConstants.java
index bc35935e..b0e3d5fe 100644
--- a/android/support/mediacompat/testlib/IntentConstants.java
+++ b/android/support/mediacompat/testlib/IntentConstants.java
@@ -17,11 +17,18 @@
package android.support.mediacompat.testlib;
/**
- * Constants used for sending intent between client and service apks.
+ * Constants used for sending intent between client and service apps.
*/
public class IntentConstants {
public static final String ACTION_CALL_MEDIA_BROWSER_SERVICE_METHOD =
"android.support.mediacompat.service.action.CALL_MEDIA_BROWSER_SERVICE_METHOD";
+ public static final String ACTION_CALL_MEDIA_SESSION_METHOD =
+ "android.support.mediacompat.service.action.CALL_MEDIA_SESSION_METHOD";
+ public static final String ACTION_CALL_MEDIA_CONTROLLER_METHOD =
+ "android.support.mediacompat.client.action.CALL_MEDIA_CONTROLLER_METHOD";
+ public static final String ACTION_CALL_TRANSPORT_CONTROLS_METHOD =
+ "android.support.mediacompat.client.action.CALL_TRANSPORT_CONTROLS_METHOD";
public static final String KEY_METHOD_ID = "method_id";
public static final String KEY_ARGUMENT = "argument";
+ public static final String KEY_SESSION_TOKEN = "session_token";
}
diff --git a/android/support/mediacompat/testlib/MediaControllerConstants.java b/android/support/mediacompat/testlib/MediaControllerConstants.java
new file mode 100644
index 00000000..1de00efc
--- /dev/null
+++ b/android/support/mediacompat/testlib/MediaControllerConstants.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2017 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 android.support.mediacompat.testlib;
+
+/**
+ * Constants for testing the media controller.
+ */
+public class MediaControllerConstants {
+
+ // MediaControllerCompat methods.
+ public static final int SEND_COMMAND = 201;
+ public static final int ADD_QUEUE_ITEM = 202;
+ public static final int ADD_QUEUE_ITEM_WITH_INDEX = 203;
+ public static final int REMOVE_QUEUE_ITEM = 204;
+
+ // TransportControls methods.
+ public static final int PLAY = 301;
+ public static final int PAUSE = 302;
+ public static final int STOP = 303;
+ public static final int FAST_FORWARD = 304;
+ public static final int REWIND = 305;
+ public static final int SKIP_TO_PREVIOUS = 306;
+ public static final int SKIP_TO_NEXT = 307;
+ public static final int SEEK_TO = 308;
+ public static final int SET_RATING = 309;
+ public static final int PLAY_FROM_MEDIA_ID = 310;
+ public static final int PLAY_FROM_SEARCH = 311;
+ public static final int PLAY_FROM_URI = 312;
+ public static final int SEND_CUSTOM_ACTION = 313;
+ public static final int SEND_CUSTOM_ACTION_PARCELABLE = 314;
+ public static final int SKIP_TO_QUEUE_ITEM = 315;
+ public static final int PREPARE = 316;
+ public static final int PREPARE_FROM_MEDIA_ID = 317;
+ public static final int PREPARE_FROM_SEARCH = 318;
+ public static final int PREPARE_FROM_URI = 319;
+ public static final int SET_CAPTIONING_ENABLED = 320;
+ public static final int SET_REPEAT_MODE = 321;
+ public static final int SET_SHUFFLE_MODE = 322;
+}
diff --git a/android/support/mediacompat/testlib/MediaSessionConstants.java b/android/support/mediacompat/testlib/MediaSessionConstants.java
new file mode 100644
index 00000000..79381e5e
--- /dev/null
+++ b/android/support/mediacompat/testlib/MediaSessionConstants.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2017 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 android.support.mediacompat.testlib;
+
+/**
+ * Constants for testing the media session.
+ */
+public class MediaSessionConstants {
+
+ // MediaSessionCompat methods.
+ public static final int SET_EXTRAS = 101;
+ public static final int SET_FLAGS = 102;
+ public static final int SET_METADATA = 103;
+ public static final int SET_PLAYBACK_STATE = 104;
+ public static final int SET_QUEUE = 105;
+ public static final int SET_QUEUE_TITLE = 106;
+ public static final int SET_SESSION_ACTIVITY = 107;
+ public static final int SET_CAPTIONING_ENABLED = 108;
+ public static final int SET_REPEAT_MODE = 109;
+ public static final int SET_SHUFFLE_MODE = 110;
+ public static final int SEND_SESSION_EVENT = 112;
+ public static final int SET_ACTIVE = 113;
+ public static final int RELEASE = 114;
+ public static final int SET_PLAYBACK_TO_LOCAL = 115;
+ public static final int SET_PLAYBACK_TO_REMOTE = 116;
+ public static final int SET_RATING_TYPE = 117;
+
+ public static final String TEST_SESSION_TAG = "test-session-tag";
+ public static final String SERVICE_PACKAGE_NAME = "android.support.mediacompat.service.test";
+ public static final String TEST_KEY = "test-key";
+ public static final String TEST_VALUE = "test-val";
+ public static final String TEST_SESSION_EVENT = "test-session-event";
+ public static final String TEST_COMMAND = "test-command";
+ public static final int TEST_FLAGS = 5;
+ public static final int TEST_CURRENT_VOLUME = 10;
+ public static final int TEST_MAX_VOLUME = 11;
+ public static final long TEST_QUEUE_ID_1 = 10L;
+ public static final long TEST_QUEUE_ID_2 = 20L;
+ public static final String TEST_MEDIA_ID_1 = "media_id_1";
+ public static final String TEST_MEDIA_ID_2 = "media_id_2";
+ public static final long TEST_ACTION = 55L;
+
+ public static final int TEST_ERROR_CODE = 0x3;
+ public static final String TEST_ERROR_MSG = "test-error-msg";
+}
diff --git a/android/support/transition/AutoTransition.java b/android/support/transition/AutoTransition.java
index 02b49e26..bf39c3c3 100644
--- a/android/support/transition/AutoTransition.java
+++ b/android/support/transition/AutoTransition.java
@@ -45,9 +45,9 @@ public class AutoTransition extends TransitionSet {
private void init() {
setOrdering(ORDERING_SEQUENTIAL);
- addTransition(new Fade(Fade.OUT)).
- addTransition(new ChangeBounds()).
- addTransition(new Fade(Fade.IN));
+ addTransition(new Fade(Fade.OUT))
+ .addTransition(new ChangeBounds())
+ .addTransition(new Fade(Fade.IN));
}
}
diff --git a/android/support/v17/leanback/widget/GridLayoutManager.java b/android/support/v17/leanback/widget/GridLayoutManager.java
index 81431972..af37f77a 100644
--- a/android/support/v17/leanback/widget/GridLayoutManager.java
+++ b/android/support/v17/leanback/widget/GridLayoutManager.java
@@ -2240,10 +2240,24 @@ final class GridLayoutManager extends RecyclerView.LayoutManager {
focusToViewInLayout(hadFocus, scrollToFocus, -deltaPrimary, -deltaSecondary);
appendVisibleItems();
prependVisibleItems();
- removeInvisibleViewsAtFront();
- removeInvisibleViewsAtEnd();
+ // b/67370222: do not removeInvisibleViewsAtFront/End() in the loop, otherwise
+ // loop may bounce between scroll forward and scroll backward forever. Example:
+ // Assuming there are 19 items, child#18 and child#19 are both in RV, we are
+ // trying to focus to child#18 and there are 200px remaining scroll distance.
+ // 1 focusToViewInLayout() tries scroll forward 50 px to align focused child#18 on
+ // right edge, but there to compensate remaining scroll 200px, also scroll
+ // backward 200px, 150px pushes last child#19 out side of right edge.
+ // 2 removeInvisibleViewsAtEnd() remove last child#19, updateScrollLimits()
+ // invalidates scroll max
+ // 3 In next iteration, when scroll max/min is unknown, focusToViewInLayout() will
+ // align focused child#18 at center of screen.
+ // 4 Because #18 is aligned at center, appendVisibleItems() will fill child#19 to
+ // the right.
+ // 5 (back to 1 and loop forever)
} while (mGrid.getFirstVisibleIndex() != oldFirstVisible
|| mGrid.getLastVisibleIndex() != oldLastVisible);
+ removeInvisibleViewsAtFront();
+ removeInvisibleViewsAtEnd();
if (state.willRunPredictiveAnimations()) {
fillScrapViewsInPostLayout();
diff --git a/android/support/v4/content/res/ResourcesCompat.java b/android/support/v4/content/res/ResourcesCompat.java
index 4c70ce93..15b8ce9a 100644
--- a/android/support/v4/content/res/ResourcesCompat.java
+++ b/android/support/v4/content/res/ResourcesCompat.java
@@ -307,11 +307,11 @@ public final class ResourcesCompat {
*/
@RestrictTo(LIBRARY_GROUP)
public static Typeface getFont(@NonNull Context context, @FontRes int id, TypedValue value,
- int style) throws NotFoundException {
+ int style, @Nullable FontCallback fontCallback) throws NotFoundException {
if (context.isRestricted()) {
return null;
}
- return loadFont(context, id, value, style, null /* callback */, null /* handler */,
+ return loadFont(context, id, value, style, fontCallback, null /* handler */,
true /* isXmlRequest */);
}
diff --git a/android/support/v4/media/RatingCompat.java b/android/support/v4/media/RatingCompat.java
index b538cac4..e70243f8 100644
--- a/android/support/v4/media/RatingCompat.java
+++ b/android/support/v4/media/RatingCompat.java
@@ -18,6 +18,7 @@ package android.support.v4.media;
import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
+import android.media.Rating;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
@@ -326,25 +327,25 @@ public final class RatingCompat implements Parcelable {
*/
public static RatingCompat fromRating(Object ratingObj) {
if (ratingObj != null && Build.VERSION.SDK_INT >= 19) {
- final int ratingStyle = RatingCompatKitkat.getRatingStyle(ratingObj);
+ final int ratingStyle = ((Rating) ratingObj).getRatingStyle();
final RatingCompat rating;
- if (RatingCompatKitkat.isRated(ratingObj)) {
+ if (((Rating) ratingObj).isRated()) {
switch (ratingStyle) {
case RATING_HEART:
- rating = newHeartRating(RatingCompatKitkat.hasHeart(ratingObj));
+ rating = newHeartRating(((Rating) ratingObj).hasHeart());
break;
case RATING_THUMB_UP_DOWN:
- rating = newThumbRating(RatingCompatKitkat.isThumbUp(ratingObj));
+ rating = newThumbRating(((Rating) ratingObj).isThumbUp());
break;
case RATING_3_STARS:
case RATING_4_STARS:
case RATING_5_STARS:
rating = newStarRating(ratingStyle,
- RatingCompatKitkat.getStarRating(ratingObj));
+ ((Rating) ratingObj).getStarRating());
break;
case RATING_PERCENTAGE:
rating = newPercentageRating(
- RatingCompatKitkat.getPercentRating(ratingObj));
+ ((Rating) ratingObj).getPercentRating());
break;
default:
return null;
@@ -372,25 +373,25 @@ public final class RatingCompat implements Parcelable {
if (isRated()) {
switch (mRatingStyle) {
case RATING_HEART:
- mRatingObj = RatingCompatKitkat.newHeartRating(hasHeart());
+ mRatingObj = Rating.newHeartRating(hasHeart());
break;
case RATING_THUMB_UP_DOWN:
- mRatingObj = RatingCompatKitkat.newThumbRating(isThumbUp());
+ mRatingObj = Rating.newThumbRating(isThumbUp());
break;
case RATING_3_STARS:
case RATING_4_STARS:
case RATING_5_STARS:
- mRatingObj = RatingCompatKitkat.newStarRating(mRatingStyle,
+ mRatingObj = Rating.newStarRating(mRatingStyle,
getStarRating());
break;
case RATING_PERCENTAGE:
- mRatingObj = RatingCompatKitkat.newPercentageRating(getPercentRating());
+ mRatingObj = Rating.newPercentageRating(getPercentRating());
break;
default:
return null;
}
} else {
- mRatingObj = RatingCompatKitkat.newUnratedRating(mRatingStyle);
+ mRatingObj = Rating.newUnratedRating(mRatingStyle);
}
}
return mRatingObj;
diff --git a/android/support/v4/media/RatingCompatKitkat.java b/android/support/v4/media/RatingCompatKitkat.java
deleted file mode 100644
index 1d3fa505..00000000
--- a/android/support/v4/media/RatingCompatKitkat.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2014 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 android.support.v4.media;
-
-import android.media.Rating;
-import android.support.annotation.RequiresApi;
-
-@RequiresApi(19)
-class RatingCompatKitkat {
- public static Object newUnratedRating(int ratingStyle) {
- return Rating.newUnratedRating(ratingStyle);
- }
-
- public static Object newHeartRating(boolean hasHeart) {
- return Rating.newHeartRating(hasHeart);
- }
-
- public static Object newThumbRating(boolean thumbIsUp) {
- return Rating.newThumbRating(thumbIsUp);
- }
-
- public static Object newStarRating(int starRatingStyle, float starRating) {
- return Rating.newStarRating(starRatingStyle, starRating);
- }
-
- public static Object newPercentageRating(float percent) {
- return Rating.newPercentageRating(percent);
- }
-
- public static boolean isRated(Object ratingObj) {
- return ((Rating)ratingObj).isRated();
- }
-
- public static int getRatingStyle(Object ratingObj) {
- return ((Rating)ratingObj).getRatingStyle();
- }
-
- public static boolean hasHeart(Object ratingObj) {
- return ((Rating)ratingObj).hasHeart();
- }
-
- public static boolean isThumbUp(Object ratingObj) {
- return ((Rating)ratingObj).isThumbUp();
- }
-
- public static float getStarRating(Object ratingObj) {
- return ((Rating)ratingObj).getStarRating();
- }
-
- public static float getPercentRating(Object ratingObj) {
- return ((Rating)ratingObj).getPercentRating();
- }
-}
diff --git a/android/support/v4/provider/FontsContractCompat.java b/android/support/v4/provider/FontsContractCompat.java
index 9ef1b0b0..09261869 100644
--- a/android/support/v4/provider/FontsContractCompat.java
+++ b/android/support/v4/provider/FontsContractCompat.java
@@ -303,6 +303,9 @@ public class FontsContractCompat {
final ArrayList<ReplyCallback<TypefaceResult>> replies;
synchronized (sLock) {
replies = sPendingReplies.get(id);
+ if (replies == null) {
+ return; // Nobody requested replies. Do nothing.
+ }
sPendingReplies.remove(id);
}
for (int i = 0; i < replies.size(); ++i) {
diff --git a/android/support/v7/app/MediaRouteButton.java b/android/support/v7/app/MediaRouteButton.java
index d3f7020b..fdbcf9ad 100644
--- a/android/support/v7/app/MediaRouteButton.java
+++ b/android/support/v7/app/MediaRouteButton.java
@@ -121,8 +121,7 @@ public class MediaRouteButton extends View {
}
public MediaRouteButton(Context context, AttributeSet attrs, int defStyleAttr) {
- super(MediaRouterThemeHelper.createThemedContext(context, defStyleAttr), attrs,
- defStyleAttr);
+ super(MediaRouterThemeHelper.createThemedButtonContext(context), attrs, defStyleAttr);
context = getContext();
mRouter = MediaRouter.getInstance(context);
diff --git a/android/support/v7/app/MediaRouteChooserDialog.java b/android/support/v7/app/MediaRouteChooserDialog.java
index 0ab2eb11..17364efb 100644
--- a/android/support/v7/app/MediaRouteChooserDialog.java
+++ b/android/support/v7/app/MediaRouteChooserDialog.java
@@ -92,10 +92,8 @@ public class MediaRouteChooserDialog extends AppCompatDialog {
}
public MediaRouteChooserDialog(Context context, int theme) {
- // If we pass theme ID of 0 to AppCompatDialog, it will apply dialogTheme on the context,
- // which may override our style settings. Passes our uppermost theme ID to prevent this.
- super(MediaRouterThemeHelper.createThemedContext(context, theme),
- theme == 0 ? MediaRouterThemeHelper.createThemeForDialog(context, theme) : theme);
+ super(context = MediaRouterThemeHelper.createThemedDialogContext(context, theme, false),
+ MediaRouterThemeHelper.createThemedDialogStyle(context));
context = getContext();
mRouter = MediaRouter.getInstance(context);
diff --git a/android/support/v7/app/MediaRouteControllerDialog.java b/android/support/v7/app/MediaRouteControllerDialog.java
index 4b9a17a3..d89bf21e 100644
--- a/android/support/v7/app/MediaRouteControllerDialog.java
+++ b/android/support/v7/app/MediaRouteControllerDialog.java
@@ -201,12 +201,8 @@ public class MediaRouteControllerDialog extends AlertDialog {
}
public MediaRouteControllerDialog(Context context, int theme) {
- // If we pass theme ID of 0 to AppCompatDialog, it will apply dialogTheme on the context,
- // which may override our style settings. Passes our uppermost theme ID to prevent this.
- super(MediaRouterThemeHelper.createThemedContext(context,
- MediaRouterThemeHelper.getAlertDialogResolvedTheme(context, theme)), theme == 0
- ? MediaRouterThemeHelper.createThemeForDialog(context, MediaRouterThemeHelper
- .getAlertDialogResolvedTheme(context, theme)) : theme);
+ super(context = MediaRouterThemeHelper.createThemedDialogContext(context, theme, true),
+ MediaRouterThemeHelper.createThemedDialogStyle(context));
mContext = getContext();
mControllerCallback = new MediaControllerCallback();
diff --git a/android/support/v7/app/MediaRouterThemeHelper.java b/android/support/v7/app/MediaRouterThemeHelper.java
index 9ef218e0..69e40ac7 100644
--- a/android/support/v7/app/MediaRouterThemeHelper.java
+++ b/android/support/v7/app/MediaRouterThemeHelper.java
@@ -42,47 +42,76 @@ final class MediaRouterThemeHelper {
private MediaRouterThemeHelper() {
}
- /**
- * Creates a themed context based on the explicit style resource or the parent context's default
- * theme.
- * <p>
- * The theme which will be applied on top of the parent {@code context}'s theme is determined
- * by the primary color defined in the given {@code style}, or in the parent {@code context}.
+ static Context createThemedButtonContext(Context context) {
+ // Apply base Media Router theme.
+ context = new ContextThemeWrapper(context, getRouterThemeId(context));
+
+ // Apply custom Media Router theme.
+ int style = getThemeResource(context, R.attr.mediaRouteTheme);
+ if (style != 0) {
+ context = new ContextThemeWrapper(context, style);
+ }
+
+ return context;
+ }
+
+ /*
+ * The following two methods are to be used in conjunction. They should be used to prepare
+ * the context and theme for a super class constructor (the latter method relies on the
+ * former method to properly prepare the context):
+ * super(context = createThemedDialogContext(context, theme),
+ * createThemedDialogStyle(context));
*
- * @param context the parent context
- * @param style the resource ID of the style against which to inflate this context, or
- * {@code 0} to use the parent {@code context}'s default theme.
- * @return The themed context.
+ * It will apply theme in the following order (style lookups will be done in reverse):
+ * 1) Current theme
+ * 2) Supplied theme
+ * 3) Base Media Router theme
+ * 4) Custom Media Router theme, if provided
*/
- static Context createThemedContext(Context context, int style) {
- // First, apply dialog property overlay.
- Context themedContext =
- new ContextThemeWrapper(context, getStyledRouterThemeId(context, style));
- int customizedThemeId = getThemeResource(context, R.attr.mediaRouteTheme);
- return customizedThemeId == 0 ? themedContext
- : new ContextThemeWrapper(themedContext, customizedThemeId);
+ static Context createThemedDialogContext(Context context, int theme, boolean alertDialog) {
+ // 1) Current theme is already applied to the context
+
+ // 2) If no theme is supplied, look it up from the context (dialogTheme/alertDialogTheme)
+ if (theme == 0) {
+ theme = getThemeResource(context, !alertDialog
+ ? android.support.v7.appcompat.R.attr.dialogTheme
+ : android.support.v7.appcompat.R.attr.alertDialogTheme);
+ }
+ // Apply it
+ context = new ContextThemeWrapper(context, theme);
+
+ // 3) If a custom Media Router theme is provided then apply the base theme
+ if (getThemeResource(context, R.attr.mediaRouteTheme) != 0) {
+ context = new ContextThemeWrapper(context, getRouterThemeId(context));
+ }
+
+ return context;
}
+ // This method should be used in conjunction with the previous method.
+ static int createThemedDialogStyle(Context context) {
+ // 4) Apply the custom Media Router theme
+ int theme = getThemeResource(context, R.attr.mediaRouteTheme);
+ if (theme == 0) {
+ // 3) No custom MediaRouther theme was provided so apply the base theme instead
+ theme = getRouterThemeId(context);
+ }
- /**
- * Creates the theme resource ID intended to be used by dialogs.
- */
- static int createThemeForDialog(Context context, int style) {
- int customizedThemeId = getThemeResource(context, R.attr.mediaRouteTheme);
- return customizedThemeId != 0 ? customizedThemeId : getStyledRouterThemeId(context, style);
+ return theme;
}
+ // END. Previous two methods should be used in conjunction.
- public static int getThemeResource(Context context, int attr) {
+ static int getThemeResource(Context context, int attr) {
TypedValue value = new TypedValue();
return context.getTheme().resolveAttribute(attr, value, true) ? value.resourceId : 0;
}
- public static float getDisabledAlpha(Context context) {
+ static float getDisabledAlpha(Context context) {
TypedValue value = new TypedValue();
return context.getTheme().resolveAttribute(android.R.attr.disabledAlpha, value, true)
? value.getFloat() : 0.5f;
}
- public static @ControllerColorType int getControllerColor(Context context, int style) {
+ static @ControllerColorType int getControllerColor(Context context, int style) {
int primaryColor = getThemeColor(context, style,
android.support.v7.appcompat.R.attr.colorPrimary);
if (ColorUtils.calculateContrast(COLOR_WHITE_ON_DARK_BACKGROUND, primaryColor)
@@ -92,7 +121,7 @@ final class MediaRouterThemeHelper {
return COLOR_DARK_ON_LIGHT_BACKGROUND;
}
- public static int getButtonTextColor(Context context) {
+ static int getButtonTextColor(Context context) {
int primaryColor = getThemeColor(context, 0,
android.support.v7.appcompat.R.attr.colorPrimary);
int backgroundColor = getThemeColor(context, 0, android.R.attr.colorBackground);
@@ -104,7 +133,7 @@ final class MediaRouterThemeHelper {
return primaryColor;
}
- public static void setMediaControlsBackgroundColor(
+ static void setMediaControlsBackgroundColor(
Context context, View mainControls, View groupControls, boolean hasGroup) {
int primaryColor = getThemeColor(context, 0,
android.support.v7.appcompat.R.attr.colorPrimary);
@@ -124,7 +153,7 @@ final class MediaRouterThemeHelper {
groupControls.setTag(primaryDarkColor);
}
- public static void setVolumeSliderColor(
+ static void setVolumeSliderColor(
Context context, MediaRouteVolumeSlider volumeSlider, View backgroundView) {
int controllerColor = getControllerColor(context, 0);
if (Color.alpha(controllerColor) != 0xFF) {
@@ -136,23 +165,10 @@ final class MediaRouterThemeHelper {
volumeSlider.setColor(controllerColor);
}
- // This is copied from {@link AlertDialog#resolveDialogTheme} to pre-evaluate theme in advance.
- public static int getAlertDialogResolvedTheme(Context context, int themeResId) {
- if (themeResId >= 0x01000000) { // start of real resource IDs.
- return themeResId;
- } else {
- TypedValue outValue = new TypedValue();
- context.getTheme().resolveAttribute(
- android.support.v7.appcompat.R.attr.alertDialogTheme, outValue, true);
- return outValue.resourceId;
- }
- }
-
private static boolean isLightTheme(Context context) {
TypedValue value = new TypedValue();
- return context.getTheme().resolveAttribute(
- android.support.v7.appcompat.R.attr.isLightTheme, value, true)
- && value.data != 0;
+ return context.getTheme().resolveAttribute(android.support.v7.appcompat.R.attr.isLightTheme,
+ value, true) && value.data != 0;
}
private static int getThemeColor(Context context, int style, int attr) {
@@ -173,16 +189,16 @@ final class MediaRouterThemeHelper {
return value.data;
}
- private static int getStyledRouterThemeId(Context context, int style) {
+ private static int getRouterThemeId(Context context) {
int themeId;
if (isLightTheme(context)) {
- if (getControllerColor(context, style) == COLOR_DARK_ON_LIGHT_BACKGROUND) {
+ if (getControllerColor(context, 0) == COLOR_DARK_ON_LIGHT_BACKGROUND) {
themeId = R.style.Theme_MediaRouter_Light;
} else {
themeId = R.style.Theme_MediaRouter_Light_DarkControlPanel;
}
} else {
- if (getControllerColor(context, style) == COLOR_DARK_ON_LIGHT_BACKGROUND) {
+ if (getControllerColor(context, 0) == COLOR_DARK_ON_LIGHT_BACKGROUND) {
themeId = R.style.Theme_MediaRouter_LightControlPanel;
} else {
themeId = R.style.Theme_MediaRouter;
diff --git a/android/support/v7/recyclerview/extensions/ListAdapterHelperTest.java b/android/support/v7/recyclerview/extensions/ListAdapterHelperTest.java
deleted file mode 100644
index aab74172..00000000
--- a/android/support/v7/recyclerview/extensions/ListAdapterHelperTest.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2017 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 android.support.v7.recyclerview.extensions;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.verifyZeroInteractions;
-
-import android.arch.paging.TestExecutor;
-import android.support.annotation.NonNull;
-import android.support.test.filters.SmallTest;
-import android.support.v7.util.ListUpdateCallback;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-import java.util.Arrays;
-
-@SmallTest
-@RunWith(JUnit4.class)
-public class ListAdapterHelperTest {
- private TestExecutor mMainThread = new TestExecutor();
- private TestExecutor mBackgroundThread = new TestExecutor();
-
-
- private static final DiffCallback<String> STRING_DIFF_CALLBACK = new DiffCallback<String>() {
- @Override
- public boolean areItemsTheSame(@NonNull String oldItem, @NonNull String newItem) {
- return oldItem.equals(newItem);
- }
-
- @Override
- public boolean areContentsTheSame(@NonNull String oldItem, @NonNull String newItem) {
- return oldItem.equals(newItem);
- }
- };
-
- private static final ListUpdateCallback IGNORE_CALLBACK = new ListUpdateCallback() {
- @Override
- public void onInserted(int position, int count) {
- }
-
- @Override
- public void onRemoved(int position, int count) {
- }
-
- @Override
- public void onMoved(int fromPosition, int toPosition) {
- }
-
- @Override
- public void onChanged(int position, int count, Object payload) {
- }
- };
-
-
- private <T> ListAdapterHelper<T> createHelper(
- ListUpdateCallback listUpdateCallback, DiffCallback<T> diffCallback) {
- return new ListAdapterHelper<T>(listUpdateCallback,
- new ListAdapterConfig.Builder<T>()
- .setDiffCallback(diffCallback)
- .setMainThreadExecutor(mMainThread)
- .setBackgroundThreadExecutor(mBackgroundThread)
- .build());
- }
-
- @Test
- public void initialState() {
- ListUpdateCallback callback = mock(ListUpdateCallback.class);
- ListAdapterHelper<String> helper = createHelper(callback, STRING_DIFF_CALLBACK);
- assertEquals(0, helper.getItemCount());
- verifyZeroInteractions(callback);
- }
-
- @Test(expected = IndexOutOfBoundsException.class)
- public void getEmpty() {
- ListAdapterHelper<String> helper = createHelper(IGNORE_CALLBACK, STRING_DIFF_CALLBACK);
- helper.getItem(0);
- }
-
- @Test(expected = IndexOutOfBoundsException.class)
- public void getNegative() {
- ListAdapterHelper<String> helper = createHelper(IGNORE_CALLBACK, STRING_DIFF_CALLBACK);
- helper.setList(Arrays.asList("a", "b"));
- helper.getItem(-1);
- }
-
- @Test(expected = IndexOutOfBoundsException.class)
- public void getPastEnd() {
- ListAdapterHelper<String> helper = createHelper(IGNORE_CALLBACK, STRING_DIFF_CALLBACK);
- helper.setList(Arrays.asList("a", "b"));
- helper.getItem(2);
- }
-
- @Test
- public void setListSimple() {
- ListUpdateCallback callback = mock(ListUpdateCallback.class);
- ListAdapterHelper<String> helper = createHelper(callback, STRING_DIFF_CALLBACK);
-
- helper.setList(Arrays.asList("a", "b"));
-
- assertEquals(2, helper.getItemCount());
- assertEquals("a", helper.getItem(0));
- assertEquals("b", helper.getItem(1));
-
- verify(callback).onInserted(0, 2);
- verifyNoMoreInteractions(callback);
- drain();
- verifyNoMoreInteractions(callback);
- }
-
- @Test
- public void setListUpdate() {
- ListUpdateCallback callback = mock(ListUpdateCallback.class);
- ListAdapterHelper<String> helper = createHelper(callback, STRING_DIFF_CALLBACK);
-
- // initial list (immediate)
- helper.setList(Arrays.asList("a", "b"));
- verify(callback).onInserted(0, 2);
- verifyNoMoreInteractions(callback);
- drain();
- verifyNoMoreInteractions(callback);
-
- // update (deferred)
- helper.setList(Arrays.asList("a", "b", "c"));
- verifyNoMoreInteractions(callback);
- drain();
- verify(callback).onInserted(2, 1);
- verifyNoMoreInteractions(callback);
-
- // clear (immediate)
- helper.setList(null);
- verify(callback).onRemoved(0, 3);
- verifyNoMoreInteractions(callback);
- drain();
- verifyNoMoreInteractions(callback);
-
- }
-
- private void drain() {
- boolean executed;
- do {
- executed = mBackgroundThread.executeAll();
- executed |= mMainThread.executeAll();
- } while (executed);
- }
-}
diff --git a/android/support/v7/util/DiffUtil.java b/android/support/v7/util/DiffUtil.java
index 6302666f..ebc33f31 100644
--- a/android/support/v7/util/DiffUtil.java
+++ b/android/support/v7/util/DiffUtil.java
@@ -16,6 +16,7 @@
package android.support.v7.util;
+import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
import android.support.v7.widget.RecyclerView;
@@ -348,6 +349,72 @@ public class DiffUtil {
}
/**
+ * Callback for calculating the diff between two non-null items in a list.
+ * <p>
+ * {@link Callback} serves two roles - list indexing, and item diffing. ItemCallback handles
+ * just the second of these, which allows separation of code that indexes into an array or List
+ * from the presentation-layer and content specific diffing code.
+ *
+ * @param <T> Type of items to compare.
+ */
+ public abstract static class ItemCallback<T> {
+ /**
+ * Called to check whether two objects represent the same item.
+ * <p>
+ * For example, if your items have unique ids, this method should check their id equality.
+ *
+ * @param oldItem The item in the old list.
+ * @param newItem The item in the new list.
+ * @return True if the two items represent the same object or false if they are different.
+ *
+ * @see Callback#areItemsTheSame(int, int)
+ */
+ public abstract boolean areItemsTheSame(@NonNull T oldItem, @NonNull T newItem);
+
+ /**
+ * Called to check whether two items have the same data.
+ * <p>
+ * This information is used to detect if the contents of an item have changed.
+ * <p>
+ * This method to check equality instead of {@link Object#equals(Object)} so that you can
+ * change its behavior depending on your UI.
+ * <p>
+ * For example, if you are using DiffUtil with a
+ * {@link android.support.v7.widget.RecyclerView.Adapter RecyclerView.Adapter}, you should
+ * return whether the items' visual representations are the same.
+ * <p>
+ * This method is called only if {@link #areItemsTheSame(T, T)} returns {@code true} for
+ * these items.
+ *
+ * @param oldItem The item in the old list.
+ * @param newItem The item in the new list.
+ * @return True if the contents of the items are the same or false if they are different.
+ *
+ * @see Callback#areContentsTheSame(int, int)
+ */
+ public abstract boolean areContentsTheSame(@NonNull T oldItem, @NonNull T newItem);
+
+ /**
+ * When {@link #areItemsTheSame(T, T)} returns {@code true} for two items and
+ * {@link #areContentsTheSame(T, T)} returns false for them, this method is called to
+ * get a payload about the change.
+ * <p>
+ * For example, if you are using DiffUtil with {@link RecyclerView}, you can return the
+ * particular field that changed in the item and your
+ * {@link android.support.v7.widget.RecyclerView.ItemAnimator ItemAnimator} can use that
+ * information to run the correct animation.
+ * <p>
+ * Default implementation returns {@code null}.
+ *
+ * @see Callback#getChangePayload(int, int)
+ */
+ @SuppressWarnings({"WeakerAccess", "unused"})
+ public Object getChangePayload(@NonNull T oldItem, @NonNull T newItem) {
+ return null;
+ }
+ }
+
+ /**
* Snakes represent a match between two lists. It is optionally prefixed or postfixed with an
* add or remove operation. See the Myers' paper for details.
*/
diff --git a/android/support/v7/widget/AppCompatTextHelper.java b/android/support/v7/widget/AppCompatTextHelper.java
index 51510aa2..fa6196f5 100644
--- a/android/support/v7/widget/AppCompatTextHelper.java
+++ b/android/support/v7/widget/AppCompatTextHelper.java
@@ -29,6 +29,7 @@ import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.RequiresApi;
import android.support.annotation.RestrictTo;
+import android.support.v4.content.res.ResourcesCompat;
import android.support.v4.widget.TextViewCompat;
import android.support.v7.appcompat.R;
import android.text.method.PasswordTransformationMethod;
@@ -36,6 +37,8 @@ import android.util.AttributeSet;
import android.util.TypedValue;
import android.widget.TextView;
+import java.lang.ref.WeakReference;
+
@RequiresApi(9)
class AppCompatTextHelper {
@@ -63,6 +66,7 @@ class AppCompatTextHelper {
private int mStyle = Typeface.NORMAL;
private Typeface mFontTypeface;
+ private boolean mAsyncFontPending;
AppCompatTextHelper(TextView view) {
mView = view;
@@ -213,8 +217,23 @@ class AppCompatTextHelper {
? R.styleable.TextAppearance_android_fontFamily
: R.styleable.TextAppearance_fontFamily;
if (!context.isRestricted()) {
+ final WeakReference<TextView> textViewWeak = new WeakReference<>(mView);
+ ResourcesCompat.FontCallback replyCallback = new ResourcesCompat.FontCallback() {
+ @Override
+ public void onFontRetrieved(@NonNull Typeface typeface) {
+ onAsyncTypefaceReceived(textViewWeak, typeface);
+ }
+
+ @Override
+ public void onFontRetrievalFailed(int reason) {
+ // Do nothing.
+ }
+ };
try {
- mFontTypeface = a.getFont(fontFamilyId, mStyle);
+ // Note the callback will be triggered on the UI thread.
+ mFontTypeface = a.getFont(fontFamilyId, mStyle, replyCallback);
+ // If this call gave us an immediate result, ignore any pending callbacks.
+ mAsyncFontPending = mFontTypeface == null;
} catch (UnsupportedOperationException | Resources.NotFoundException e) {
// Expected if it is not a font resource.
}
@@ -222,12 +241,16 @@ class AppCompatTextHelper {
if (mFontTypeface == null) {
// Try with String. This is done by TextView JB+, but fails in ICS
String fontFamilyName = a.getString(fontFamilyId);
- mFontTypeface = Typeface.create(fontFamilyName, mStyle);
+ if (fontFamilyName != null) {
+ mFontTypeface = Typeface.create(fontFamilyName, mStyle);
+ }
}
return;
}
if (a.hasValue(R.styleable.TextAppearance_android_typeface)) {
+ // Ignore previous pending fonts
+ mAsyncFontPending = false;
int typefaceIndex = a.getInt(R.styleable.TextAppearance_android_typeface, SANS);
switch (typefaceIndex) {
case SANS:
@@ -245,6 +268,16 @@ class AppCompatTextHelper {
}
}
+ private void onAsyncTypefaceReceived(WeakReference<TextView> textViewWeak, Typeface typeface) {
+ if (mAsyncFontPending) {
+ mFontTypeface = typeface;
+ final TextView textView = textViewWeak.get();
+ if (textView != null) {
+ textView.setTypeface(typeface, mStyle);
+ }
+ }
+ }
+
void onSetTextAppearance(Context context, int resId) {
final TintTypedArray a = TintTypedArray.obtainStyledAttributes(context,
resId, R.styleable.TextAppearance);
diff --git a/android/support/v7/widget/RecyclerView.java b/android/support/v7/widget/RecyclerView.java
index 7009733c..4bc17a86 100644
--- a/android/support/v7/widget/RecyclerView.java
+++ b/android/support/v7/widget/RecyclerView.java
@@ -6408,16 +6408,16 @@ public class RecyclerView extends ViewGroup implements ScrollingView, NestedScro
}
void markKnownViewsInvalid() {
- if (mAdapter != null && mAdapter.hasStableIds()) {
- final int cachedCount = mCachedViews.size();
- for (int i = 0; i < cachedCount; i++) {
- final ViewHolder holder = mCachedViews.get(i);
- if (holder != null) {
- holder.addFlags(ViewHolder.FLAG_UPDATE | ViewHolder.FLAG_INVALID);
- holder.addChangePayload(null);
- }
+ final int cachedCount = mCachedViews.size();
+ for (int i = 0; i < cachedCount; i++) {
+ final ViewHolder holder = mCachedViews.get(i);
+ if (holder != null) {
+ holder.addFlags(ViewHolder.FLAG_UPDATE | ViewHolder.FLAG_INVALID);
+ holder.addChangePayload(null);
}
- } else {
+ }
+
+ if (mAdapter == null || !mAdapter.hasStableIds()) {
// we cannot re-use cached views in this case. Recycle them all
recycleAndClearCachedViews();
}
diff --git a/android/support/v7/widget/TintTypedArray.java b/android/support/v7/widget/TintTypedArray.java
index 22709551..384c4615 100644
--- a/android/support/v7/widget/TintTypedArray.java
+++ b/android/support/v7/widget/TintTypedArray.java
@@ -106,7 +106,8 @@ public class TintTypedArray {
* not a font resource.
*/
@Nullable
- public Typeface getFont(@StyleableRes int index, int style) {
+ public Typeface getFont(@StyleableRes int index, int style,
+ @Nullable ResourcesCompat.FontCallback fontCallback) {
final int resourceId = mWrapped.getResourceId(index, 0);
if (resourceId == 0) {
return null;
@@ -114,7 +115,7 @@ public class TintTypedArray {
if (mTypedValue == null) {
mTypedValue = new TypedValue();
}
- return ResourcesCompat.getFont(mContext, resourceId, mTypedValue, style);
+ return ResourcesCompat.getFont(mContext, resourceId, mTypedValue, style, fontCallback);
}
public int length() {
diff --git a/android/support/wear/ambient/AmbientMode.java b/android/support/wear/ambient/AmbientMode.java
index 7fbbbb3f..db53dfc1 100644
--- a/android/support/wear/ambient/AmbientMode.java
+++ b/android/support/wear/ambient/AmbientMode.java
@@ -22,7 +22,6 @@ import android.content.Context;
import android.os.Bundle;
import android.support.annotation.CallSuper;
import android.support.annotation.VisibleForTesting;
-import android.util.Log;
import com.google.android.wearable.compat.WearableActivityController;
@@ -263,20 +262,6 @@ public final class AmbientMode extends Fragment {
AmbientController() {}
/**
- * Sets whether this activity's task should be moved to the front when the system exits
- * ambient mode. If true, the activity's task may be moved to the front if it was the last
- * activity to be running when ambient started, depending on how much time the system spent
- * in ambient mode.
- */
- public void setAutoResumeEnabled(boolean enabled) {
- if (mDelegate != null) {
- mDelegate.setAutoResumeEnabled(enabled);
- } else {
- Log.w(TAG, "The fragment is not yet fully initialized, this call is a no-op");
- }
- }
-
- /**
* @return {@code true} if the activity is currently in ambient.
*/
public boolean isAmbient() {