[Manual Merge] Add a new car-uxr-client-lib
Its first ever residents are:
- UxrContentLimiter
- A set of stylables and a parser to parser config specified using these.
BUG: 160737115
BUG: 159766205
Test: manual
Change-Id: I1eb810f038fb81cb2f38484c4c6a296dd6879f50
diff --git a/car-uxr-client-lib/Android.bp b/car-uxr-client-lib/Android.bp
new file mode 100644
index 0000000..85f99de
--- /dev/null
+++ b/car-uxr-client-lib/Android.bp
@@ -0,0 +1,35 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_library {
+
+ name: "car-uxr-client-lib",
+
+ srcs: ["src/**/*.java"],
+
+ optimize: {
+ enabled: false,
+ },
+
+ libs: [
+ "android.car",
+ ],
+
+ static_libs: [
+ "androidx.recyclerview_recyclerview",
+ "androidx.lifecycle_lifecycle-common-java8",
+ "car-ui-lib",
+ ],
+}
diff --git a/car-uxr-client-lib/AndroidManifest.xml b/car-uxr-client-lib/AndroidManifest.xml
new file mode 100644
index 0000000..9550419
--- /dev/null
+++ b/car-uxr-client-lib/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.car.uxr">
+</manifest>
diff --git a/car-uxr-client-lib/OWNERS b/car-uxr-client-lib/OWNERS
new file mode 100644
index 0000000..55f7d43
--- /dev/null
+++ b/car-uxr-client-lib/OWNERS
@@ -0,0 +1,9 @@
+# People who can approve changes for submission.
+johnchoi@google.com
+stenning@google.com
+igorr@google.com
+
+# Engs
+pardis@google.com
+jjoz@google.com
+
diff --git a/car-uxr-client-lib/README.md b/car-uxr-client-lib/README.md
new file mode 100644
index 0000000..7f57376
--- /dev/null
+++ b/car-uxr-client-lib/README.md
@@ -0,0 +1,7 @@
+# Android Automotive App-side User Experience Restriction (UXR) library
+Components and resources designed to reduce the amount of work needed by
+Automotive app developers to add User Experience Restriction Engine
+support to their apps.
+
+Source: /packages/apps/Car/libs/car-uxr-client-lib
+
diff --git a/car-uxr-client-lib/res/values/attrs.xml b/car-uxr-client-lib/res/values/attrs.xml
new file mode 100644
index 0000000..084e30d
--- /dev/null
+++ b/car-uxr-client-lib/res/values/attrs.xml
@@ -0,0 +1,41 @@
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<!--
+ ~ An example uxr_config.xml file would look like:
+ ~ <Mapping xmlns:app="http://schemas.android.com/apk/res-auto">
+ ~ <ListConfig
+ ~ app:id="@+id/call_log_list_uxr_config"
+ ~ app:maxLength="10"
+ ~ app:message="@string/call_log_scrolling_limited_message"
+ ~ />
+ ~ </Mapping>
+ -->
+<resources>
+ <!-- Global container of uxr related app configs -->
+ <declare-styleable name="CarUxRestrictionsAppConfig"/>
+ <!-- The mapping of lists to their uxr related override values. -->
+ <declare-styleable name="CarUxRestrictionsAppConfig_Mapping"/>
+
+ <!-- Uxr related overrides for a specific list -->
+ <declare-styleable name="CarUxRestrictionsAppConfig_ListConfig">
+ <!-- Id of ListConfig, used to differentiate them -->
+ <attr name="id" format="reference"/>
+ <!-- Used to limit the length of a list. -->
+ <attr name="maxLength" format="integer"/>
+ <!-- Used to educate users why their scrolling experience is limited. -->
+ <attr name="message" format="string"/>
+ </declare-styleable>
+</resources>
\ No newline at end of file
diff --git a/car-uxr-client-lib/src/com/android/car/uxr/CarUxRestrictionsAppConfig.java b/car-uxr-client-lib/src/com/android/car/uxr/CarUxRestrictionsAppConfig.java
new file mode 100644
index 0000000..49634ca
--- /dev/null
+++ b/car-uxr-client-lib/src/com/android/car/uxr/CarUxRestrictionsAppConfig.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.uxr;
+
+import android.content.Context;
+
+import androidx.annotation.IdRes;
+import androidx.annotation.Nullable;
+import androidx.annotation.StringRes;
+import androidx.annotation.XmlRes;
+
+import java.util.Map;
+
+/**
+ * A container class for app specific Car User Experience Restriction override configurations.
+ *
+ * <p>{@link #getInstance(Context, int)} will returned a lazily populated cached reference to the
+ * configurations object that is read using
+ * {@link CarUxRestrictionsAppConfigParser#parseConfig(Context, int)}.
+ *
+ * <p>{@link #getMapping()} can be used to access the mapping of component IDs to configurations
+ * specific to that component.
+ */
+public class CarUxRestrictionsAppConfig {
+
+ private final Map<Integer, ListConfig> mMapping;
+ private static CarUxRestrictionsAppConfig sInstance;
+
+ CarUxRestrictionsAppConfig(Map<Integer, ListConfig> mapping) {
+ mMapping = mapping;
+ }
+
+ /**
+ * Returns a cached reference to the {@link CarUxRestrictionsAppConfig} object
+ * resulting from parsing the contents of {@code xmlRes} xml resource.
+ *
+ * @param context - the app context
+ * @param xmlRes - the xml resource that contains the UXR override configs.
+ */
+ public static CarUxRestrictionsAppConfig getInstance(Context context, @XmlRes int xmlRes) {
+ if (sInstance == null) {
+ sInstance = CarUxRestrictionsAppConfigParser.parseConfig(context, xmlRes);
+ }
+
+ return sInstance;
+ }
+
+ /**
+ * Returns a {@link Map} of Resource Ids as ints to {@link ListConfig} objects.
+ */
+ public Map<Integer, ListConfig> getMapping() {
+ return mMapping;
+ }
+
+ /**
+ * A class representing Car User Experience Restriction override configurations for a list UI
+ * component.
+ */
+ public static class ListConfig {
+ @IdRes
+ private final int mId;
+ private final Integer mContentLimit;
+ @StringRes
+ private final Integer mScrollingLimitedMessageResId;
+
+ private ListConfig(@IdRes int id, @Nullable Integer contentLimit,
+ @StringRes Integer scrollingLimitedMessageResId) {
+ mId = id;
+ mContentLimit = contentLimit;
+ mScrollingLimitedMessageResId = scrollingLimitedMessageResId;
+ }
+
+ /**
+ * Returns a {@code Builder} that can be used to build a {@link ListConfig} object for a
+ * component identified with the provided {@code id}.
+ *
+ * @param id - an identifier for the component whose behavior needs to be overridden with
+ * the configurations specified in the resulting {@link ListConfig} object.
+ */
+ public static Builder builder(@IdRes int id) {
+ return new Builder(id);
+ }
+
+ /**
+ * Returns the identifier for the component whose behavior needs to be overridden by this
+ * config object.
+ */
+ @IdRes
+ public int getId() {
+ return mId;
+ }
+
+ /**
+ * Returns the item limit to impose on the contents of the corresponding list component.
+ */
+ @Nullable
+ public Integer getContentLimit() {
+ return mContentLimit;
+ }
+
+ /**
+ * Returns the string resource ID to use when educating users about why the content in the
+ * list they're browsing has been limited.
+ */
+ @Nullable
+ @StringRes
+ public Integer getScrollingLimitedMessageResId() {
+ return mScrollingLimitedMessageResId;
+ }
+
+ /**
+ * A Builder for {@link ListConfig}.
+ */
+ public static class Builder {
+ @IdRes
+ private final int mId;
+ private Integer mContentLimit;
+ @StringRes
+ private Integer mScrollingLimitedMessageResId;
+
+
+ /**
+ * Constructs a {@code Builder} that can be used to build a {@link ListConfig} object
+ * for a component identified with the provided {@code id}.
+ *
+ * @param id - an identifier for the component whose behavior needs to be overridden
+ * with the configurations specified in the resulting {@link ListConfig}
+ * object.
+ */
+ private Builder(@IdRes int id) {
+ mId = id;
+ }
+
+ /**
+ * Sets the item limit to impose on the contents of the corresponding list component.
+ *
+ * @param contentLimit - the item limit
+ * @return this {@code Builder} object to facilitate chaining.
+ */
+ public Builder setContentLimit(int contentLimit) {
+ mContentLimit = contentLimit;
+ return this;
+ }
+
+ /**
+ * Sets the string resource ID to use when educating users about why the content in the
+ * * list they're browsing has been limited.
+ *
+ * @param scrollingLimitedMessageResId - an educational message string resource ID
+ * @return this {@code Builder} object to facilitate chaining.
+ */
+ public Builder setScrollingLimitedMessageResId(
+ @StringRes int scrollingLimitedMessageResId) {
+ mScrollingLimitedMessageResId = scrollingLimitedMessageResId;
+ return this;
+ }
+
+ /**
+ * Build and return a {@link ListConfig} object with the values provided to this
+ * {@code Builder} object.
+ */
+ public ListConfig build() {
+ return new ListConfig(mId, mContentLimit, mScrollingLimitedMessageResId);
+ }
+ }
+ }
+}
diff --git a/car-uxr-client-lib/src/com/android/car/uxr/CarUxRestrictionsAppConfigParser.java b/car-uxr-client-lib/src/com/android/car/uxr/CarUxRestrictionsAppConfigParser.java
new file mode 100644
index 0000000..341e426
--- /dev/null
+++ b/car-uxr-client-lib/src/com/android/car/uxr/CarUxRestrictionsAppConfigParser.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.car.uxr;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Xml;
+import android.view.View;
+
+import androidx.annotation.XmlRes;
+
+import com.android.car.uxr.CarUxRestrictionsAppConfig.ListConfig;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A parser that can read an XML resource file and construct the corresponding
+ * {@link CarUxRestrictionsAppConfig} object.
+ *
+ * See car-uxr-client-lib/res/values/attrs.xml for the definition of the relevant XML tags.
+ */
+public class CarUxRestrictionsAppConfigParser {
+ private static final String TAG = "UxrAppConfigParser";
+
+ static CarUxRestrictionsAppConfig parseConfig(Context context, @XmlRes int xmlRes) {
+ try (XmlResourceParser parser = context.getResources().getXml(xmlRes)) {
+ AttributeSet attrs = Xml.asAttributeSet(parser);
+ Map<Integer, ListConfig> mapping = new HashMap<>();
+
+ // Skip over the xml version tag
+ parser.next();
+ // Skip over the copyright comment block
+ parser.next();
+ parser.require(XmlPullParser.START_TAG, null, "Mapping");
+ while (parser.next() != XmlPullParser.END_TAG) {
+ ListConfig listConfig = parseListConfigItem(context, parser, attrs);
+ mapping.put(listConfig.getId(), listConfig);
+ }
+
+ return new CarUxRestrictionsAppConfig(mapping);
+ } catch (XmlPullParserException | IOException e) {
+ throw new RuntimeException("Unable to parse CarUxRestrictionsAppConfig", e);
+ }
+ }
+
+ private static ListConfig parseListConfigItem(
+ Context context, XmlResourceParser parser, AttributeSet attrs)
+ throws XmlPullParserException, IOException {
+
+ parser.require(XmlPullParser.START_TAG, null, "ListConfig");
+
+ TypedArray a = context.obtainStyledAttributes(
+ attrs, R.styleable.CarUxRestrictionsAppConfig_ListConfig);
+
+ try {
+ int id = a.getResourceId(R.styleable.CarUxRestrictionsAppConfig_ListConfig_id,
+ View.NO_ID);
+ if (id == View.NO_ID) {
+ throw new IllegalStateException("Id field is required");
+ }
+
+ boolean messageExists = a.hasValue(
+ R.styleable.CarUxRestrictionsAppConfig_ListConfig_message);
+ int messageResId = a.getResourceId(
+ R.styleable.CarUxRestrictionsAppConfig_ListConfig_message, View.NO_ID);
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, messageExists
+ ? "message field is set to " + messageResId
+ : "message field not specified");
+ }
+
+ boolean maxLengthExists = a.hasValue(
+ R.styleable.CarUxRestrictionsAppConfig_ListConfig_maxLength);
+ int maxLengthInt = a.getInt(
+ R.styleable.CarUxRestrictionsAppConfig_ListConfig_maxLength, 0);
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, maxLengthExists
+ ? "maxLength field is set to " + maxLengthInt
+ : "maxLength field not specified");
+ }
+
+ parser.next();
+ parser.require(XmlPullParser.END_TAG, null, "ListConfig");
+
+ ListConfig.Builder builder = ListConfig.builder(id);
+ if (maxLengthExists) {
+ builder.setContentLimit(maxLengthInt);
+ }
+ if (messageExists) {
+ builder.setScrollingLimitedMessageResId(messageResId);
+ }
+ return builder.build();
+ } finally {
+ a.recycle();
+ }
+ }
+}
diff --git a/car-uxr-client-lib/src/com/android/car/uxr/LifeCycleObserverUxrContentLimiter.java b/car-uxr-client-lib/src/com/android/car/uxr/LifeCycleObserverUxrContentLimiter.java
new file mode 100644
index 0000000..3c8905e
--- /dev/null
+++ b/car-uxr-client-lib/src/com/android/car/uxr/LifeCycleObserverUxrContentLimiter.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.uxr;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.DefaultLifecycleObserver;
+import androidx.lifecycle.LifecycleOwner;
+
+import com.android.car.ui.recyclerview.ContentLimiting;
+
+/**
+ * An implementation of {@link UxrContentLimiter} interface that also provides the functionality
+ * necessary for a {@link DefaultLifecycleObserver}.
+ *
+ * <p>Relies heavily on the {@link UxrContentLimiterImpl} implementation of the
+ * {@link UxrContentLimiter} interface.
+ *
+ * <p>For example, you could do the following to get yourself a lifecycle aware {@link
+ * UxrContentLimiter}:
+ * <pre>{@code
+ * new LifeCycleObserverUxrContentLimiter(new UxrContentLimiterImpl(context,xmlRes));
+ * }</pre>
+ */
+public class LifeCycleObserverUxrContentLimiter
+ implements UxrContentLimiter, DefaultLifecycleObserver {
+
+ private final UxrContentLimiterImpl mDelegate;
+
+ public LifeCycleObserverUxrContentLimiter(UxrContentLimiterImpl delegate) {
+ mDelegate = delegate;
+ }
+
+ @Override
+ public void onStart(@NonNull LifecycleOwner owner) {
+ mDelegate.start();
+ }
+
+ @Override
+ public void onStop(@NonNull LifecycleOwner owner) {
+ mDelegate.stop();
+ }
+
+ @Override
+ public void setAdapter(ContentLimiting adapter) {
+ mDelegate.setAdapter(adapter);
+ }
+}
diff --git a/car-uxr-client-lib/src/com/android/car/uxr/UxrContentLimiter.java b/car-uxr-client-lib/src/com/android/car/uxr/UxrContentLimiter.java
new file mode 100644
index 0000000..9fd877e
--- /dev/null
+++ b/car-uxr-client-lib/src/com/android/car/uxr/UxrContentLimiter.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.uxr;
+
+import com.android.car.ui.recyclerview.ContentLimiting;
+
+/**
+ * An interface to facilitate the content limiting ability of {@link ContentLimiting}
+ * {@link androidx.recyclerview.widget.RecyclerView.Adapter} objects based on changes to the state
+ * of the car.
+ */
+public interface UxrContentLimiter {
+
+ /**
+ * Registers the given {@link ContentLimiting} with this {@code UxrContentLimiter}.
+ *
+ * <p>That means that when the car state changes, if necessary, this
+ * {@code UxrContentLimiter} will limit the content in the given adapter.
+ *
+ * @param adapter - the adapter to associate with this content limiter.
+ */
+ void setAdapter(ContentLimiting adapter);
+}
diff --git a/car-uxr-client-lib/src/com/android/car/uxr/UxrContentLimiterImpl.java b/car-uxr-client-lib/src/com/android/car/uxr/UxrContentLimiterImpl.java
new file mode 100644
index 0000000..ce22cca
--- /dev/null
+++ b/car-uxr-client-lib/src/com/android/car/uxr/UxrContentLimiterImpl.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.uxr;
+
+import android.car.drivingstate.CarUxRestrictions;
+import android.content.Context;
+import android.util.Log;
+
+import androidx.annotation.IdRes;
+import androidx.annotation.NonNull;
+import androidx.annotation.XmlRes;
+
+import com.android.car.ui.recyclerview.ContentLimiting;
+import com.android.car.ui.utils.CarUxRestrictionsUtil;
+import com.android.car.uxr.CarUxRestrictionsAppConfig.ListConfig;
+
+/**
+ * A class that can work together with a {@link ContentLimiting} {@link
+ * androidx.recyclerview.widget.RecyclerView.Adapter} object to provide content limiting ability
+ * based on changes to the state of the car, by listening for the latest {@link CarUxRestrictions}.
+ *
+ * <p>This class manages 3 things:
+ * <ul>
+ * <li> Communications with the User Experience Restriction Engine
+ * <li> Looking up app-side overrides for customizing the content-limiting behavior of a given
+ * list of items in a particular screen
+ * <li> Relaying the relevant parts of that information to the registered
+ * adapter at the right time
+ * </ul>
+ *
+ * <p>The app-side overrides are accessed via the {@link CarUxRestrictionsAppConfig} object.
+ *
+ * <p>Because all but one of the dependencies for this class can be instantiated as soon as a
+ * {@link Context} is available, we provide a separate {@link #setAdapter(ContentLimiting)}
+ * API for linking the targeted adapter. That way the registration can happen in a different part of
+ * code, and potentially in a different lifecycle method to provide maximum flexibility.
+ */
+public class UxrContentLimiterImpl implements UxrContentLimiter {
+
+ private ContentLimiting mAdapter;
+ private ListConfig mListConfig;
+
+ private final CarUxRestrictionsUtil mCarUxRestrictionsUtil;
+ private final CarUxRestrictionsAppConfig mCarUxRestrictionsAppConfig;
+ private final CarUxRestrictionsUtil.OnUxRestrictionsChangedListener mListener =
+ new Listener();
+
+ private class Listener implements CarUxRestrictionsUtil.OnUxRestrictionsChangedListener {
+ private static final String TAG = "ContentLimitListener";
+
+ @Override
+ public void onRestrictionsChanged(@NonNull CarUxRestrictions carUxRestrictions) {
+ if (mAdapter == null) {
+ Log.w(TAG, "No adapter registered.");
+ return;
+ }
+
+ int maxItems = getMaxItemsToUse(carUxRestrictions, mAdapter.getConfigurationId());
+ logD("New limit " + maxItems);
+ mAdapter.setMaxItems(maxItems);
+ }
+
+ private int getMaxItemsToUse(CarUxRestrictions carUxRestrictions, @IdRes int id) {
+ // Unrelated restrictions are active. Quit early.
+ if ((carUxRestrictions.getActiveRestrictions()
+ & CarUxRestrictions.UX_RESTRICTIONS_LIMIT_CONTENT)
+ == 0) {
+ logD("Lists are unrestricted.");
+ return ContentLimiting.UNLIMITED;
+ }
+
+ if (mListConfig == null || mListConfig.getContentLimit() == null) {
+ logD("No configs found for adapter with the ID: " + id
+ + " Using the default limit");
+ return carUxRestrictions.getMaxCumulativeContentItems();
+ }
+
+ logD("Using the provided override.");
+ return mListConfig.getContentLimit();
+ }
+
+ private void logD(String s) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, s);
+ }
+ }
+ }
+
+ /**
+ * Constructs a {@link UxrContentLimiterImpl} object given the app context and the XML resource
+ * file to parse the User Experience Restriction override configs from.
+ *
+ * @param context - the app context
+ * @param xmlRes - the UXR override config XML resource
+ */
+ public UxrContentLimiterImpl(Context context, @XmlRes int xmlRes) {
+ mCarUxRestrictionsUtil = CarUxRestrictionsUtil.getInstance(context);
+ mCarUxRestrictionsAppConfig = CarUxRestrictionsAppConfig.getInstance(context, xmlRes);
+ }
+
+ @Override
+ public void setAdapter(ContentLimiting adapter) {
+ mAdapter = adapter;
+ int key = mAdapter.getConfigurationId();
+ if (mCarUxRestrictionsAppConfig.getMapping().containsKey(key)) {
+ mListConfig = mCarUxRestrictionsAppConfig.getMapping().get(key);
+ Integer overriddenMessageResId = mListConfig.getScrollingLimitedMessageResId();
+ if (overriddenMessageResId != null) {
+ mAdapter.setScrollingLimitedMessageResId(overriddenMessageResId);
+ }
+ }
+ }
+
+ /**
+ * Start listening for changes to {@link CarUxRestrictions}.
+ */
+ public void start() {
+ mCarUxRestrictionsUtil.register(mListener);
+ }
+
+ /**
+ * Stop listening for changes to {@link CarUxRestrictions}.
+ */
+ public void stop() {
+ mCarUxRestrictionsUtil.unregister(mListener);
+ }
+}