/* * 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}. * *

This class manages 3 things: *

* *

The app-side overrides are accessed via the {@link CarUxRestrictionsAppConfig} object. * *

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); } }