diff --git a/AndroidManifest.xml b/AndroidManifest.xml index af690d920b1..6b9c637d2b4 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -191,12 +191,6 @@ - - - - - - - - - - @@ -897,18 +885,10 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -2545,18 +2497,10 @@ - - - - - - @@ -2954,13 +2898,8 @@ - - - - - - @@ -2980,11 +2916,8 @@ - - @@ -2995,20 +2928,12 @@ android:icon="@drawable/ic_homepage_system_dashboard" android:taskAffinity="com.android.settings" android:parentActivityName="Settings"> - - - - - - - - - - - - + summaries = new ArrayList<>(); - - if (types == null || types.length == 0) { - summaries.add(mContext.getString(R.string.account_dashboard_default_summary)); - } else { - // Show up to 3 account types, ignore any null value - int accountToAdd = Math.min(3, types.length); - - for (int i = 0; i < types.length && accountToAdd > 0; i++) { - final CharSequence label = authHelper.getLabelForType(mContext, types[i]); - if (TextUtils.isEmpty(label)) { - continue; - } - - summaries.add(bidiFormatter.unicodeWrap(label)); - accountToAdd--; - } - } - mSummaryLoader.setSummary(this, ListFormatter.getInstance().format(summaries)); - } - } - } - - public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY - = (activity, summaryLoader) -> new SummaryProvider(activity, summaryLoader); - public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = new BaseSearchIndexProvider() { @Override diff --git a/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java b/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java index e9b076eabeb..223b78ff95e 100644 --- a/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java +++ b/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java @@ -15,7 +15,6 @@ */ package com.android.settings.connecteddevice; -import android.app.Activity; import android.content.Context; import android.provider.SearchIndexableResource; @@ -24,7 +23,6 @@ import androidx.annotation.VisibleForTesting; import com.android.internal.logging.nano.MetricsProto; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; -import com.android.settings.dashboard.SummaryLoader; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.lifecycle.Lifecycle; @@ -92,35 +90,6 @@ public class ConnectedDeviceDashboardFragment extends DashboardFragment { use(DiscoverableFooterPreferenceController.class).init(this); } - @VisibleForTesting - static class SummaryProvider implements SummaryLoader.SummaryProvider { - - private final Context mContext; - private final SummaryLoader mSummaryLoader; - - public SummaryProvider(Context context, SummaryLoader summaryLoader) { - mContext = context; - mSummaryLoader = summaryLoader; - } - - @Override - public void setListening(boolean listening) { - if (listening) { - mSummaryLoader.setSummary(this, mContext.getText(AdvancedConnectedDeviceController. - getConnectedDevicesSummaryResourceId(mContext))); - } - } - } - - public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY - = new SummaryLoader.SummaryProviderFactory() { - @Override - public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity, - SummaryLoader summaryLoader) { - return new SummaryProvider(activity, summaryLoader); - } - }; - /** * For Search. */ diff --git a/src/com/android/settings/dashboard/DashboardAdapter.java b/src/com/android/settings/dashboard/DashboardAdapter.java deleted file mode 100644 index 307f6ba93c0..00000000000 --- a/src/com/android/settings/dashboard/DashboardAdapter.java +++ /dev/null @@ -1,407 +0,0 @@ -/* - * Copyright (C) 2015 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.settings.dashboard; - -import android.content.Context; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.Icon; -import android.os.Bundle; -import android.service.settings.suggestions.Suggestion; -import android.text.TextUtils; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; - -import androidx.annotation.VisibleForTesting; -import androidx.fragment.app.FragmentActivity; -import androidx.recyclerview.widget.DiffUtil; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - -import com.android.internal.logging.nano.MetricsProto.MetricsEvent; -import com.android.settings.R; -import com.android.settings.R.id; -import com.android.settings.dashboard.DashboardData.ConditionHeaderData; -import com.android.settings.dashboard.suggestions.SuggestionAdapter; -import com.android.settings.homepage.conditional.ConditionAdapter; -import com.android.settings.homepage.conditional.ConditionManager; -import com.android.settings.homepage.conditional.ConditionalCard; -import com.android.settings.overlay.FeatureFactory; -import com.android.settings.widget.RoundedHomepageIcon; -import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; -import com.android.settingslib.core.lifecycle.Lifecycle; -import com.android.settingslib.core.lifecycle.LifecycleObserver; -import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState; -import com.android.settingslib.drawer.DashboardCategory; -import com.android.settingslib.drawer.Tile; -import com.android.settingslib.suggestions.SuggestionControllerMixinCompat; -import com.android.settingslib.utils.IconCache; - -import java.util.List; - -public class DashboardAdapter extends RecyclerView.Adapter - implements SummaryLoader.SummaryConsumer, SuggestionAdapter.Callback, LifecycleObserver, - OnSaveInstanceState { - public static final String TAG = "DashboardAdapter"; - private static final String STATE_CATEGORY_LIST = "category_list"; - - @VisibleForTesting - static final String STATE_CONDITION_EXPANDED = "condition_expanded"; - - private final IconCache mCache; - private final Context mContext; - private final MetricsFeatureProvider mMetricsFeatureProvider; - private final DashboardFeatureProvider mDashboardFeatureProvider; - private boolean mFirstFrameDrawn; - private RecyclerView mRecyclerView; - private SuggestionAdapter mSuggestionAdapter; - private ConditionManager mConditionManager; - - @VisibleForTesting - DashboardData mDashboardData; - - private View.OnClickListener mTileClickListener = new View.OnClickListener() { - @Override - public void onClick(View v) { - //TODO: get rid of setTag/getTag - mDashboardFeatureProvider.openTileIntent((FragmentActivity) mContext, - (Tile) v.getTag()); - } - }; - - public DashboardAdapter(Context context, Bundle savedInstanceState, - ConditionManager conditionManager, - SuggestionControllerMixinCompat suggestionControllerMixin, Lifecycle lifecycle) { - - DashboardCategory category = null; - boolean conditionExpanded = false; - - mContext = context; - final FeatureFactory factory = FeatureFactory.getFactory(context); - mMetricsFeatureProvider = factory.getMetricsFeatureProvider(); - mDashboardFeatureProvider = factory.getDashboardFeatureProvider(context); - mCache = new IconCache(context); - mConditionManager = conditionManager; - mSuggestionAdapter = new SuggestionAdapter(mContext, suggestionControllerMixin, - savedInstanceState, this /* callback */, lifecycle); - - setHasStableIds(true); - - if (savedInstanceState != null) { - category = savedInstanceState.getParcelable(STATE_CATEGORY_LIST); - conditionExpanded = savedInstanceState.getBoolean( - STATE_CONDITION_EXPANDED, conditionExpanded); - } - - if (lifecycle != null) { - lifecycle.addObserver(this); - } - - mDashboardData = new DashboardData.Builder() - .setSuggestions(mSuggestionAdapter.getSuggestions()) - .setCategory(category) - .setConditionExpanded(conditionExpanded) - .build(); - } - - public void setSuggestions(List data) { - final DashboardData prevData = mDashboardData; - mDashboardData = new DashboardData.Builder(prevData) - .setSuggestions(data) - .build(); - notifyDashboardDataChanged(prevData); - } - - public void setCategory(DashboardCategory category) { - final DashboardData prevData = mDashboardData; - Log.d(TAG, "adapter setCategory called"); - mDashboardData = new DashboardData.Builder(prevData) - .setCategory(category) - .build(); - notifyDashboardDataChanged(prevData); - } - - public void setConditions(List conditions) { - final DashboardData prevData = mDashboardData; - Log.d(TAG, "adapter setConditions called"); - mDashboardData = new DashboardData.Builder(prevData) - .setConditions(conditions) - .build(); - notifyDashboardDataChanged(prevData); - } - - @Override - public void onSuggestionClosed(Suggestion suggestion) { - final List list = mDashboardData.getSuggestions(); - if (list == null || list.size() == 0 || !list.remove(suggestion)) { - return; - } - if (list.isEmpty()) { - // The only suggestion is dismissed, and the the empty suggestion container will - // remain as the dashboard item. Need to refresh the dashboard list. - setSuggestions(null); - } else { - setSuggestions(list); - } - } - - @Override - public void notifySummaryChanged(Tile tile) { - final int position = mDashboardData.getPositionByTile(tile); - if (position != DashboardData.POSITION_NOT_FOUND) { - // Since usually tile in parameter and tile in mCategories are same instance, - // which is hard to be detected by DiffUtil, so we notifyItemChanged directly. - notifyItemChanged(position, mDashboardData.getItemTypeByPosition(position)); - } - } - - @Override - public DashboardItemHolder onCreateViewHolder(ViewGroup parent, int viewType) { - final View view = LayoutInflater.from(parent.getContext()).inflate(viewType, parent, false); - if (viewType == R.layout.condition_header) { - return new ConditionHeaderHolder(view); - } - if (viewType == R.layout.condition_container) { - return new ConditionContainerHolder(view); - } - if (viewType == R.layout.suggestion_container) { - return new SuggestionContainerHolder(view); - } - return new DashboardItemHolder(view); - } - - @Override - public void onBindViewHolder(DashboardItemHolder holder, int position) { - final int type = mDashboardData.getItemTypeByPosition(position); - switch (type) { - case R.layout.dashboard_tile: - final Tile tile = (Tile) mDashboardData.getItemEntityByPosition(position); - onBindTile(holder, tile); - holder.itemView.setTag(tile); - holder.itemView.setOnClickListener(mTileClickListener); - break; - case R.layout.suggestion_container: - onBindSuggestion((SuggestionContainerHolder) holder, position); - break; - case R.layout.condition_container: - onBindCondition((ConditionContainerHolder) holder, position); - break; - case R.layout.condition_header: - onBindConditionHeader((ConditionHeaderHolder) holder, - (ConditionHeaderData) mDashboardData.getItemEntityByPosition(position)); - break; - case R.layout.condition_footer: - holder.itemView.setOnClickListener(v -> { - mMetricsFeatureProvider.action(mContext, - MetricsEvent.ACTION_SETTINGS_CONDITION_EXPAND, false); - DashboardData prevData = mDashboardData; - mDashboardData = new DashboardData.Builder(prevData). - setConditionExpanded(false).build(); - notifyDashboardDataChanged(prevData); - scrollToTopOfConditions(); - }); - break; - } - } - - @Override - public long getItemId(int position) { - return mDashboardData.getItemIdByPosition(position); - } - - @Override - public int getItemViewType(int position) { - return mDashboardData.getItemTypeByPosition(position); - } - - @Override - public int getItemCount() { - return mDashboardData.size(); - } - - @Override - public void onAttachedToRecyclerView(RecyclerView recyclerView) { - super.onAttachedToRecyclerView(recyclerView); - // save the view so that we can scroll it when expanding/collapsing the suggestion and - // conditions. - mRecyclerView = recyclerView; - } - - public Object getItem(long itemId) { - return mDashboardData.getItemEntityById(itemId); - } - - @VisibleForTesting - void notifyDashboardDataChanged(DashboardData prevData) { - if (mFirstFrameDrawn && prevData != null) { - final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DashboardData - .ItemsDataDiffCallback(prevData.getItemList(), mDashboardData.getItemList())); - diffResult.dispatchUpdatesTo(this); - } else { - mFirstFrameDrawn = true; - notifyDataSetChanged(); - } - } - - @VisibleForTesting - void onBindConditionHeader(final ConditionHeaderHolder holder, ConditionHeaderData data) { - holder.icon.setImageDrawable(data.conditionIcons.get(0)); - if (data.conditionCount == 1) { - holder.title.setText(data.title); - holder.summary.setText(null); - holder.icons.setVisibility(View.INVISIBLE); - } else { - holder.title.setText(null); - holder.summary.setText( - mContext.getString(R.string.condition_summary, data.conditionCount)); - updateConditionIcons(data.conditionIcons, holder.icons); - holder.icons.setVisibility(View.VISIBLE); - } - - holder.itemView.setOnClickListener(v -> { - mMetricsFeatureProvider.action(mContext, - MetricsEvent.ACTION_SETTINGS_CONDITION_EXPAND, true); - final DashboardData prevData = mDashboardData; - mDashboardData = new DashboardData.Builder(prevData) - .setConditionExpanded(true).build(); - notifyDashboardDataChanged(prevData); - scrollToTopOfConditions(); - }); - } - - @VisibleForTesting - void onBindCondition(final ConditionContainerHolder holder, int position) { - final List conditions = - (List) mDashboardData.getItemEntityByPosition(position); - final ConditionAdapter adapter = new ConditionAdapter( - mContext, mConditionManager, conditions, - mDashboardData.isConditionExpanded()); - holder.data.setAdapter(adapter); - holder.data.setLayoutManager(new LinearLayoutManager(mContext)); - } - - @VisibleForTesting - void onBindSuggestion(final SuggestionContainerHolder holder, int position) { - // If there is suggestions to show, it will be at position 0 as we don't show the suggestion - // header anymore. - final List suggestions = - (List) mDashboardData.getItemEntityByPosition(position); - if (suggestions != null && suggestions.size() > 0) { - mSuggestionAdapter.setSuggestions(suggestions); - holder.data.setAdapter(mSuggestionAdapter); - } - final LinearLayoutManager layoutManager = new LinearLayoutManager(mContext); - layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); - holder.data.setLayoutManager(layoutManager); - } - - @VisibleForTesting - void onBindTile(DashboardItemHolder holder, Tile tile) { - Icon tileIcon = tile.getIcon(mContext); - Drawable icon = mCache.getIcon(tileIcon); - if (!TextUtils.equals(tileIcon.getResPackage(), mContext.getPackageName()) - && !(icon instanceof RoundedHomepageIcon)) { - icon = new RoundedHomepageIcon(mContext, icon); - ((RoundedHomepageIcon) icon).setBackgroundColor(mContext, tile); - mCache.updateIcon(tileIcon, icon); - } - holder.icon.setImageDrawable(icon); - holder.title.setText(tile.getTitle(mContext)); - final CharSequence summary = tile.getSummary(mContext); - if (!TextUtils.isEmpty(summary)) { - holder.summary.setText(summary); - holder.summary.setVisibility(View.VISIBLE); - } else { - holder.summary.setVisibility(View.GONE); - } - } - - @Override - public void onSaveInstanceState(Bundle outState) { - final DashboardCategory category = mDashboardData.getCategory(); - if (category != null) { - outState.putParcelable(STATE_CATEGORY_LIST, category); - } - outState.putBoolean(STATE_CONDITION_EXPANDED, mDashboardData.isConditionExpanded()); - } - - private void updateConditionIcons(List icons, ViewGroup parent) { - if (icons == null || icons.size() < 2) { - parent.setVisibility(View.INVISIBLE); - return; - } - final LayoutInflater inflater = LayoutInflater.from(parent.getContext()); - parent.removeAllViews(); - for (int i = 1, size = icons.size(); i < size; i++) { - ImageView icon = (ImageView) inflater.inflate( - R.layout.condition_header_icon, parent, false); - icon.setImageDrawable(icons.get(i)); - parent.addView(icon); - } - parent.setVisibility(View.VISIBLE); - } - - private void scrollToTopOfConditions() { - mRecyclerView.scrollToPosition(mDashboardData.hasSuggestion() ? 1 : 0); - } - - public static class DashboardItemHolder extends RecyclerView.ViewHolder { - public final ImageView icon; - public final TextView title; - public final TextView summary; - - public DashboardItemHolder(View itemView) { - super(itemView); - icon = itemView.findViewById(android.R.id.icon); - title = itemView.findViewById(android.R.id.title); - summary = itemView.findViewById(android.R.id.summary); - } - } - - public static class ConditionHeaderHolder extends DashboardItemHolder { - public final LinearLayout icons; - public final ImageView expandIndicator; - - public ConditionHeaderHolder(View itemView) { - super(itemView); - icons = itemView.findViewById(id.additional_icons); - expandIndicator = itemView.findViewById(id.expand_indicator); - } - } - - public static class ConditionContainerHolder extends DashboardItemHolder { - public final RecyclerView data; - - public ConditionContainerHolder(View itemView) { - super(itemView); - data = itemView.findViewById(id.data); - } - } - - public static class SuggestionContainerHolder extends DashboardItemHolder { - public final RecyclerView data; - - public SuggestionContainerHolder(View itemView) { - super(itemView); - data = itemView.findViewById(id.suggestion_list); - } - } - -} diff --git a/src/com/android/settings/dashboard/DashboardData.java b/src/com/android/settings/dashboard/DashboardData.java deleted file mode 100644 index 5265b82ae92..00000000000 --- a/src/com/android/settings/dashboard/DashboardData.java +++ /dev/null @@ -1,416 +0,0 @@ -/* - * Copyright (C) 2016 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.settings.dashboard; - -import android.annotation.IntDef; -import android.graphics.drawable.Drawable; -import android.service.settings.suggestions.Suggestion; -import android.text.TextUtils; - -import androidx.annotation.VisibleForTesting; -import androidx.recyclerview.widget.DiffUtil; - -import com.android.settings.R; -import com.android.settings.homepage.conditional.ConditionalCard; -import com.android.settingslib.drawer.DashboardCategory; -import com.android.settingslib.drawer.Tile; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.ArrayList; -import java.util.List; - -/** - * Description about data list used in the DashboardAdapter. In the data list each item can be - * Condition, suggestion or category tile. - *

- * ItemsData has inner class Item, which represents the Item in data list. - */ -public class DashboardData { - public static final int POSITION_NOT_FOUND = -1; - - // stable id for different type of items. - @VisibleForTesting - static final int STABLE_ID_SUGGESTION_CONTAINER = 0; - static final int STABLE_ID_SUGGESTION_CONDITION_DIVIDER = 1; - @VisibleForTesting - static final int STABLE_ID_CONDITION_HEADER = 2; - @VisibleForTesting - static final int STABLE_ID_CONDITION_FOOTER = 3; - @VisibleForTesting - static final int STABLE_ID_CONDITION_CONTAINER = 4; - - private final List mItems; - private final DashboardCategory mCategory; - private final List mConditions; - private final List mSuggestions; - private final boolean mConditionExpanded; - - private DashboardData(Builder builder) { - mCategory = builder.mCategory; - mConditions = builder.mConditions; - mSuggestions = builder.mSuggestions; - mConditionExpanded = builder.mConditionExpanded; - mItems = new ArrayList<>(); - - buildItemsData(); - } - - public int getItemIdByPosition(int position) { - return mItems.get(position).id; - } - - public int getItemTypeByPosition(int position) { - return mItems.get(position).type; - } - - public Object getItemEntityByPosition(int position) { - return mItems.get(position).entity; - } - - public List getItemList() { - return mItems; - } - - public int size() { - return mItems.size(); - } - - public Object getItemEntityById(long id) { - for (final Item item : mItems) { - if (item.id == id) { - return item.entity; - } - } - return null; - } - - public DashboardCategory getCategory() { - return mCategory; - } - - public List getConditions() { - return mConditions; - } - - public List getSuggestions() { - return mSuggestions; - } - - public boolean hasSuggestion() { - return sizeOf(mSuggestions) > 0; - } - - public boolean isConditionExpanded() { - return mConditionExpanded; - } - - /** - * Find the position of the object in mItems list, using the equals method to compare - * - * @param entity the object that need to be found in list - * @return position of the object, return POSITION_NOT_FOUND if object isn't in the list - */ - public int getPositionByEntity(Object entity) { - if (entity == null) return POSITION_NOT_FOUND; - - final int size = mItems.size(); - for (int i = 0; i < size; i++) { - final Object item = mItems.get(i).entity; - if (entity.equals(item)) { - return i; - } - } - - return POSITION_NOT_FOUND; - } - - /** - * Find the position of the Tile object. - *

- * First, try to find the exact identical instance of the tile object, if not found, - * then try to find a tile has the same id. - * - * @param tile tile that need to be found - * @return position of the object, return INDEX_NOT_FOUND if object isn't in the list - */ - public int getPositionByTile(Tile tile) { - final int size = mItems.size(); - for (int i = 0; i < size; i++) { - final Object entity = mItems.get(i).entity; - if (entity == tile) { - return i; - } else if (entity instanceof Tile && tile.getId() == ((Tile) entity).getId()) { - return i; - } - } - - return POSITION_NOT_FOUND; - } - - /** - * Add item into list when {@paramref add} is true. - * - * @param item maybe {@link ConditionalCard}, {@link Tile}, {@link DashboardCategory} - * or null - * @param type type of the item, and value is the layout id - * @param stableId The stable id for this item - * @param add flag about whether to add item into list - */ - private void addToItemList(Object item, int type, int stableId, boolean add) { - if (add) { - mItems.add(new Item(item, type, stableId)); - } - } - - /** - * Build the mItems list using mConditions, mSuggestions, mCategories data - * and mIsShowingAll, mConditionExpanded flag. - */ - private void buildItemsData() { - final List conditions = mConditions; - final boolean hasConditions = sizeOf(conditions) > 0; - - final List suggestions = mSuggestions; - final boolean hasSuggestions = sizeOf(suggestions) > 0; - - /* Suggestion container. This is the card view that contains the list of suggestions. - * This will be added whenever the suggestion list is not empty */ - addToItemList(suggestions, R.layout.suggestion_container, - STABLE_ID_SUGGESTION_CONTAINER, hasSuggestions); - - /* Divider between suggestion and conditions if both are present. */ - addToItemList(null /* item */, R.layout.horizontal_divider, - STABLE_ID_SUGGESTION_CONDITION_DIVIDER, hasSuggestions && hasConditions); - - /* Condition header. This will be present when there is condition and it is collapsed */ - addToItemList(new ConditionHeaderData(conditions), - R.layout.condition_header, - STABLE_ID_CONDITION_HEADER, hasConditions && !mConditionExpanded); - - /* Condition container. This is the card view that contains the list of conditions. - * This will be added whenever the condition list is not empty and expanded */ - addToItemList(conditions, R.layout.condition_container, - STABLE_ID_CONDITION_CONTAINER, hasConditions && mConditionExpanded); - - /* Condition footer. This will be present when there is condition and it is expanded */ - addToItemList(null /* item */, R.layout.condition_footer, - STABLE_ID_CONDITION_FOOTER, hasConditions && mConditionExpanded); - - if (mCategory != null) { - final List tiles = mCategory.getTiles(); - for (int i = 0; i < tiles.size(); i++) { - final Tile tile = tiles.get(i); - addToItemList(tile, R.layout.dashboard_tile, tile.getId(), - true /* add */); - } - } - } - - private static int sizeOf(List list) { - return list == null ? 0 : list.size(); - } - - /** - * Builder used to build the ItemsData - */ - public static class Builder { - private DashboardCategory mCategory; - private List mConditions; - private List mSuggestions; - private boolean mConditionExpanded; - - public Builder() { - } - - public Builder(DashboardData dashboardData) { - mCategory = dashboardData.mCategory; - mConditions = dashboardData.mConditions; - mSuggestions = dashboardData.mSuggestions; - mConditionExpanded = dashboardData.mConditionExpanded; - } - - public Builder setCategory(DashboardCategory category) { - this.mCategory = category; - return this; - } - - public Builder setConditions(List conditions) { - this.mConditions = conditions; - return this; - } - - public Builder setSuggestions(List suggestions) { - this.mSuggestions = suggestions; - return this; - } - - public Builder setConditionExpanded(boolean expanded) { - this.mConditionExpanded = expanded; - return this; - } - - public DashboardData build() { - return new DashboardData(this); - } - } - - /** - * A DiffCallback to calculate the difference between old and new Item - * List in DashboardData - */ - public static class ItemsDataDiffCallback extends DiffUtil.Callback { - final private List mOldItems; - final private List mNewItems; - - public ItemsDataDiffCallback(List oldItems, List newItems) { - mOldItems = oldItems; - mNewItems = newItems; - } - - @Override - public int getOldListSize() { - return mOldItems.size(); - } - - @Override - public int getNewListSize() { - return mNewItems.size(); - } - - @Override - public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { - return mOldItems.get(oldItemPosition).id == mNewItems.get(newItemPosition).id; - } - - @Override - public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { - return mOldItems.get(oldItemPosition).equals(mNewItems.get(newItemPosition)); - } - - } - - /** - * An item contains the data needed in the DashboardData. - */ - static class Item { - // valid types in field type - private static final int TYPE_DASHBOARD_TILE = R.layout.dashboard_tile; - private static final int TYPE_SUGGESTION_CONTAINER = - R.layout.suggestion_container; - private static final int TYPE_CONDITION_CONTAINER = - R.layout.condition_container; - private static final int TYPE_CONDITION_HEADER = - R.layout.condition_header; - private static final int TYPE_CONDITION_FOOTER = - R.layout.condition_footer; - private static final int TYPE_SUGGESTION_CONDITION_DIVIDER = R.layout.horizontal_divider; - - @IntDef({TYPE_DASHBOARD_TILE, TYPE_SUGGESTION_CONTAINER, TYPE_CONDITION_CONTAINER, - TYPE_CONDITION_HEADER, TYPE_CONDITION_FOOTER, TYPE_SUGGESTION_CONDITION_DIVIDER}) - @Retention(RetentionPolicy.SOURCE) - public @interface ItemTypes { - } - - /** - * The main data object in item, usually is a {@link Tile}, {@link ConditionalCard} - * object. This object can also be null when the - * item is an divider line. Please refer to {@link #buildItemsData()} for - * detail usage of the Item. - */ - public final Object entity; - - /** - * The type of item, value inside is the layout id(e.g. R.layout.dashboard_tile) - */ - @ItemTypes - public final int type; - - /** - * Id of this item, used in the {@link ItemsDataDiffCallback} to identify the same item. - */ - public final int id; - - public Item(Object entity, @ItemTypes int type, int id) { - this.entity = entity; - this.type = type; - this.id = id; - } - - /** - * Override it to make comparision in the {@link ItemsDataDiffCallback} - * - * @param obj object to compared with - * @return true if the same object or has equal value. - */ - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (!(obj instanceof Item)) { - return false; - } - - final Item targetItem = (Item) obj; - if (type != targetItem.type || id != targetItem.id) { - return false; - } - - switch (type) { - case TYPE_DASHBOARD_TILE: - final Tile localTile = (Tile) entity; - final Tile targetTile = (Tile) targetItem.entity; - - // Only check id and summary for dashboard tile - return localTile.getId() == targetTile.getId() - && TextUtils.equals( - localTile.getSummaryReference(), - targetTile.getSummaryReference()); - case TYPE_SUGGESTION_CONTAINER: - case TYPE_CONDITION_CONTAINER: - // Fall through to default - default: - return entity == null ? targetItem.entity == null - : entity.equals(targetItem.entity); - } - } - } - - /** - * This class contains the data needed to build the suggestion/condition header. The data can - * also be used to check the diff in DiffUtil.Callback - */ - public static class ConditionHeaderData { - public final List conditionIcons; - public final CharSequence title; - public final int conditionCount; - - public ConditionHeaderData(List conditions) { - conditionCount = sizeOf(conditions); - title = conditionCount > 0 ? conditions.get(0).getTitle() : null; - conditionIcons = new ArrayList<>(); - if (conditions == null) { - return; - } - for (ConditionalCard card : conditions) { - conditionIcons.add(card.getIcon()); - } - } - } - -} diff --git a/src/com/android/settings/dashboard/DashboardFragmentRegistry.java b/src/com/android/settings/dashboard/DashboardFragmentRegistry.java index 9df4a05bac9..4c371ddfdc3 100644 --- a/src/com/android/settings/dashboard/DashboardFragmentRegistry.java +++ b/src/com/android/settings/dashboard/DashboardFragmentRegistry.java @@ -30,6 +30,7 @@ import com.android.settings.deviceinfo.StorageDashboardFragment; import com.android.settings.display.NightDisplaySettings; import com.android.settings.fuelgauge.PowerUsageSummary; import com.android.settings.gestures.GestureSettings; +import com.android.settings.homepage.TopLevelSettings; import com.android.settings.language.LanguageAndInputSettings; import com.android.settings.network.NetworkDashboardFragment; import com.android.settings.notification.ConfigureNotificationSettings; @@ -61,9 +62,8 @@ public class DashboardFragmentRegistry { static { PARENT_TO_CATEGORY_KEY_MAP = new ArrayMap<>(); - // TODO(b/110405144): Add the mapping when IA.homepage intent-filter is is removed. - // PARENT_TO_CATEGORY_KEY_MAP.put(TopLevelSettings.class.getName(), - // CategoryKey.CATEGORY_HOMEPAGE); + PARENT_TO_CATEGORY_KEY_MAP.put(TopLevelSettings.class.getName(), + CategoryKey.CATEGORY_HOMEPAGE); PARENT_TO_CATEGORY_KEY_MAP.put( NetworkDashboardFragment.class.getName(), CategoryKey.CATEGORY_NETWORK); PARENT_TO_CATEGORY_KEY_MAP.put(ConnectedDeviceDashboardFragment.class.getName(), diff --git a/src/com/android/settings/dashboard/DashboardItemAnimator.java b/src/com/android/settings/dashboard/DashboardItemAnimator.java deleted file mode 100644 index 51dd49eea3e..00000000000 --- a/src/com/android/settings/dashboard/DashboardItemAnimator.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2016 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.settings.dashboard; - -import androidx.core.view.ViewCompat; -import androidx.recyclerview.widget.DefaultItemAnimator; -import androidx.recyclerview.widget.RecyclerView.ViewHolder; - -import com.android.settingslib.drawer.Tile; - -public class DashboardItemAnimator extends DefaultItemAnimator { - - @Override - public boolean animateChange(ViewHolder oldHolder, ViewHolder newHolder, int fromX, int fromY, - int toX, int toY) { - final Object tag = oldHolder.itemView.getTag(); - if (tag instanceof Tile && oldHolder == newHolder) { - // When this view has other move animation running, skip this value to avoid - // animations interrupt each other. - if (!isRunning()) { - fromX += ViewCompat.getTranslationX(oldHolder.itemView); - fromY += ViewCompat.getTranslationY(oldHolder.itemView); - } - - if (fromX == toX && fromY == toY) { - dispatchMoveFinished(oldHolder); - return false; - } - } - return super.animateChange(oldHolder, newHolder, fromX, fromY, toX, toY); - } -} diff --git a/src/com/android/settings/dashboard/DashboardSummary.java b/src/com/android/settings/dashboard/DashboardSummary.java deleted file mode 100644 index 9139695b3b9..00000000000 --- a/src/com/android/settings/dashboard/DashboardSummary.java +++ /dev/null @@ -1,292 +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 com.android.settings.dashboard; - -import android.app.Activity; -import android.content.Context; -import android.os.Bundle; -import android.os.Handler; -import android.service.settings.suggestions.Suggestion; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import androidx.annotation.VisibleForTesting; -import androidx.annotation.WorkerThread; -import androidx.loader.app.LoaderManager; -import androidx.recyclerview.widget.LinearLayoutManager; - -import com.android.internal.logging.nano.MetricsProto.MetricsEvent; -import com.android.settings.R; -import com.android.settings.core.InstrumentedFragment; -import com.android.settings.core.SettingsBaseActivity; -import com.android.settings.core.SettingsBaseActivity.CategoryListener; -import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider; -import com.android.settings.homepage.conditional.ConditionListener; -import com.android.settings.homepage.conditional.ConditionManager; -import com.android.settings.homepage.conditional.FocusRecyclerView; -import com.android.settings.homepage.conditional.FocusRecyclerView.FocusListener; -import com.android.settings.overlay.FeatureFactory; -import com.android.settings.widget.ActionBarShadowController; -import com.android.settingslib.drawer.CategoryKey; -import com.android.settingslib.drawer.DashboardCategory; -import com.android.settingslib.suggestions.SuggestionControllerMixinCompat; -import com.android.settingslib.utils.ThreadUtils; - -import java.util.List; - -/** - * Deprecated in favor of {@link com.android.settings.homepage.TopLevelSettings} - * - * @deprecated - */ -@Deprecated -public class DashboardSummary extends InstrumentedFragment - implements CategoryListener, ConditionListener, - FocusListener, SuggestionControllerMixinCompat.SuggestionControllerHost { - public static final boolean DEBUG = false; - private static final boolean DEBUG_TIMING = false; - private static final int MAX_WAIT_MILLIS = 3000; - private static final String TAG = "DashboardSummary"; - - private static final String STATE_SCROLL_POSITION = "scroll_position"; - private static final String STATE_CATEGORIES_CHANGE_CALLED = "categories_change_called"; - - private final Handler mHandler = new Handler(); - - private FocusRecyclerView mDashboard; - private DashboardAdapter mAdapter; - private SummaryLoader mSummaryLoader; - private ConditionManager mConditionManager; - private LinearLayoutManager mLayoutManager; - private SuggestionControllerMixinCompat mSuggestionControllerMixin; - private DashboardFeatureProvider mDashboardFeatureProvider; - @VisibleForTesting - boolean mIsOnCategoriesChangedCalled; - private boolean mOnConditionsChangedCalled; - - private DashboardCategory mStagingCategory; - private List mStagingSuggestions; - - @Override - public int getMetricsCategory() { - return MetricsEvent.DASHBOARD_SUMMARY; - } - - @Override - public void onAttach(Context context) { - super.onAttach(context); - Log.d(TAG, "Creating SuggestionControllerMixinCompat"); - final SuggestionFeatureProvider suggestionFeatureProvider = FeatureFactory - .getFactory(context) - .getSuggestionFeatureProvider(context); - if (suggestionFeatureProvider.isSuggestionEnabled(context)) { - mSuggestionControllerMixin = new SuggestionControllerMixinCompat( - context, this /* host */, getSettingsLifecycle(), - suggestionFeatureProvider.getSuggestionServiceComponent()); - } - } - - @Override - public LoaderManager getLoaderManager() { - if (!isAdded()) { - return null; - } - return super.getLoaderManager(); - } - - @Override - public void onCreate(Bundle savedInstanceState) { - long startTime = System.currentTimeMillis(); - super.onCreate(savedInstanceState); - Log.d(TAG, "Starting DashboardSummary"); - final Activity activity = getActivity(); - mDashboardFeatureProvider = FeatureFactory.getFactory(activity) - .getDashboardFeatureProvider(activity); - - mSummaryLoader = new SummaryLoader(activity, CategoryKey.CATEGORY_HOMEPAGE); - - mConditionManager = - new ConditionManager( - activity, this /* listener */); - if (savedInstanceState != null) { - mIsOnCategoriesChangedCalled = - savedInstanceState.getBoolean(STATE_CATEGORIES_CHANGE_CALLED); - } - if (DEBUG_TIMING) { - Log.d(TAG, "onCreate took " + (System.currentTimeMillis() - startTime) + " ms"); - } - } - - @Override - public void onDestroy() { - mSummaryLoader.release(); - super.onDestroy(); - } - - @Override - public void onResume() { - long startTime = System.currentTimeMillis(); - super.onResume(); - - ((SettingsBaseActivity) getActivity()).addCategoryListener(this); - mSummaryLoader.setListening(true); - mConditionManager.startMonitoringStateChange(); - if (DEBUG_TIMING) { - Log.d(TAG, "onResume took " + (System.currentTimeMillis() - startTime) + " ms"); - } - } - - @Override - public void onPause() { - super.onPause(); - - ((SettingsBaseActivity) getActivity()).remCategoryListener(this); - mSummaryLoader.setListening(false); - mConditionManager.stopMonitoringStateChange(); - } - - @Override - public void onWindowFocusChanged(boolean hasWindowFocus) { - long startTime = System.currentTimeMillis(); - if (hasWindowFocus) { - mConditionManager.startMonitoringStateChange(); - } else { - mConditionManager.stopMonitoringStateChange(); - } - if (DEBUG_TIMING) { - Log.d(TAG, "onWindowFocusChanged took " - + (System.currentTimeMillis() - startTime) + " ms"); - } - } - - @Override - public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - if (mLayoutManager == null) { - return; - } - outState.putBoolean(STATE_CATEGORIES_CHANGE_CALLED, mIsOnCategoriesChangedCalled); - outState.putInt(STATE_SCROLL_POSITION, mLayoutManager.findFirstVisibleItemPosition()); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) { - long startTime = System.currentTimeMillis(); - final View root = inflater.inflate(R.layout.dashboard, container, false); - mDashboard = root.findViewById(R.id.dashboard_container); - mLayoutManager = new LinearLayoutManager(getContext()); - mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); - if (bundle != null) { - int scrollPosition = bundle.getInt(STATE_SCROLL_POSITION); - mLayoutManager.scrollToPosition(scrollPosition); - } - mDashboard.setLayoutManager(mLayoutManager); - mDashboard.setHasFixedSize(true); - mDashboard.setListener(this); - mDashboard.setItemAnimator(new DashboardItemAnimator()); - mAdapter = new DashboardAdapter(getContext(), bundle, - mConditionManager, - mSuggestionControllerMixin, - getSettingsLifecycle()); - mDashboard.setAdapter(mAdapter); - mSummaryLoader.setSummaryConsumer(mAdapter); - ActionBarShadowController.attachToRecyclerView( - getActivity().findViewById(R.id.search_bar_container), getSettingsLifecycle(), - mDashboard); - rebuildUI(); - if (DEBUG_TIMING) { - Log.d(TAG, "onCreateView took " - + (System.currentTimeMillis() - startTime) + " ms"); - } - return root; - } - - @VisibleForTesting - void rebuildUI() { - ThreadUtils.postOnBackgroundThread(() -> updateCategory()); - } - - @Override - public void onCategoriesChanged() { - // Bypass rebuildUI() on the first call of onCategoriesChanged, since rebuildUI() happens - // in onViewCreated as well when app starts. But, on the subsequent calls we need to - // rebuildUI() because there might be some changes to suggestions and categories. - if (mIsOnCategoriesChangedCalled) { - rebuildUI(); - } - mIsOnCategoriesChangedCalled = true; - } - - @Override - public void onConditionsChanged() { - Log.d(TAG, "onConditionsChanged"); - // Bypass refreshing the conditions on the first call of onConditionsChanged. - // onConditionsChanged is called immediately everytime we start listening to the conditions - // change when we gain window focus. Since the conditions are passed to the adapter's - // constructor when we create the view, the first handling is not necessary. - // But, on the subsequent calls we need to handle it because there might be real changes to - // conditions. - if (mOnConditionsChangedCalled) { - final boolean scrollToTop = - mLayoutManager.findFirstCompletelyVisibleItemPosition() <= 1; - mAdapter.setConditions(mConditionManager.getDisplayableCards()); - - if (scrollToTop) { - mDashboard.scrollToPosition(0); - } - } else { - mOnConditionsChangedCalled = true; - } - } - - @Override - public void onSuggestionReady(List suggestions) { - mStagingSuggestions = suggestions; - mAdapter.setSuggestions(suggestions); - if (mStagingCategory != null) { - Log.d(TAG, "Category has loaded, setting category from suggestionReady"); - mHandler.removeCallbacksAndMessages(null); - mAdapter.setCategory(mStagingCategory); - } - } - - @WorkerThread - void updateCategory() { - final DashboardCategory category = mDashboardFeatureProvider.getTilesForCategory( - CategoryKey.CATEGORY_HOMEPAGE); - mSummaryLoader.updateSummaryToCache(category); - mStagingCategory = category; - if (mSuggestionControllerMixin == null) { - ThreadUtils.postOnMainThread(() -> mAdapter.setCategory(mStagingCategory)); - return; - } - if (mSuggestionControllerMixin.isSuggestionLoaded()) { - Log.d(TAG, "Suggestion has loaded, setting suggestion/category"); - ThreadUtils.postOnMainThread(() -> { - if (mStagingSuggestions != null) { - mAdapter.setSuggestions(mStagingSuggestions); - } - mAdapter.setCategory(mStagingCategory); - }); - } else { - Log.d(TAG, "Suggestion NOT loaded, delaying setCategory by " + MAX_WAIT_MILLIS + "ms"); - mHandler.postDelayed(() -> mAdapter.setCategory(mStagingCategory), MAX_WAIT_MILLIS); - } - } -} diff --git a/src/com/android/settings/dashboard/SummaryLoader.java b/src/com/android/settings/dashboard/SummaryLoader.java index cfb64efdeb0..059cb93d9d5 100644 --- a/src/com/android/settings/dashboard/SummaryLoader.java +++ b/src/com/android/settings/dashboard/SummaryLoader.java @@ -44,7 +44,7 @@ import java.lang.reflect.Field; import java.util.List; public class SummaryLoader { - private static final boolean DEBUG = DashboardSummary.DEBUG; + private static final boolean DEBUG = false; private static final String TAG = "SummaryLoader"; public static final String SUMMARY_PROVIDER_FACTORY = "SUMMARY_PROVIDER_FACTORY"; diff --git a/src/com/android/settings/dashboard/suggestions/SuggestionAdapter.java b/src/com/android/settings/dashboard/suggestions/SuggestionAdapter.java deleted file mode 100644 index a210c8518f5..00000000000 --- a/src/com/android/settings/dashboard/suggestions/SuggestionAdapter.java +++ /dev/null @@ -1,277 +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 com.android.settings.dashboard.suggestions; - -import android.app.PendingIntent; -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Typeface; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.Icon; -import android.os.Bundle; -import android.service.settings.suggestions.Suggestion; -import android.text.TextUtils; -import android.util.DisplayMetrics; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.WindowManager; -import android.widget.LinearLayout; - -import androidx.annotation.VisibleForTesting; -import androidx.recyclerview.widget.RecyclerView; - -import com.android.internal.logging.nano.MetricsProto.MetricsEvent; -import com.android.settings.R; -import com.android.settings.dashboard.DashboardAdapter.DashboardItemHolder; -import com.android.settings.overlay.FeatureFactory; -import com.android.settingslib.Utils; -import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; -import com.android.settingslib.core.lifecycle.Lifecycle; -import com.android.settingslib.core.lifecycle.LifecycleObserver; -import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState; -import com.android.settingslib.suggestions.SuggestionControllerMixinCompat; -import com.android.settingslib.utils.IconCache; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -public class SuggestionAdapter extends RecyclerView.Adapter implements - LifecycleObserver, OnSaveInstanceState { - public static final String TAG = "SuggestionAdapter"; - - private static final String STATE_SUGGESTIONS_SHOWN_LOGGED = "suggestions_shown_logged"; - private static final String STATE_SUGGESTION_LIST = "suggestion_list"; - - private final Context mContext; - private final MetricsFeatureProvider mMetricsFeatureProvider; - private final IconCache mCache; - private final ArrayList mSuggestionsShownLogged; - private final SuggestionFeatureProvider mSuggestionFeatureProvider; - private final SuggestionControllerMixinCompat mSuggestionControllerMixin; - private final Callback mCallback; - private final CardConfig mConfig; - - private List mSuggestions; - - public interface Callback { - /** - * Called when the close button of the suggestion card is clicked. - */ - void onSuggestionClosed(Suggestion suggestion); - } - - public SuggestionAdapter(Context context, - SuggestionControllerMixinCompat suggestionControllerMixin, Bundle savedInstanceState, - Callback callback, Lifecycle lifecycle) { - mContext = context; - mSuggestionControllerMixin = suggestionControllerMixin; - mCache = new IconCache(context); - final FeatureFactory factory = FeatureFactory.getFactory(context); - mMetricsFeatureProvider = factory.getMetricsFeatureProvider(); - mSuggestionFeatureProvider = factory.getSuggestionFeatureProvider(context); - mCallback = callback; - if (savedInstanceState != null) { - mSuggestions = savedInstanceState.getParcelableArrayList(STATE_SUGGESTION_LIST); - mSuggestionsShownLogged = savedInstanceState.getStringArrayList( - STATE_SUGGESTIONS_SHOWN_LOGGED); - } else { - mSuggestionsShownLogged = new ArrayList<>(); - } - - if (lifecycle != null) { - lifecycle.addObserver(this); - } - mConfig = CardConfig.get(context); - - setHasStableIds(true); - } - - @Override - public DashboardItemHolder onCreateViewHolder(ViewGroup parent, int viewType) { - return new DashboardItemHolder(LayoutInflater.from(parent.getContext()).inflate( - viewType, parent, false)); - } - - @Override - public void onBindViewHolder(DashboardItemHolder holder, int position) { - final Suggestion suggestion = mSuggestions.get(position); - final String id = suggestion.getId(); - final int suggestionCount = mSuggestions.size(); - if (!mSuggestionsShownLogged.contains(id)) { - mMetricsFeatureProvider.action( - mContext, MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, id); - mSuggestionsShownLogged.add(id); - } - final Icon icon = suggestion.getIcon(); - final Drawable drawable = mCache.getIcon(icon); - if (drawable != null && (suggestion.getFlags() & Suggestion.FLAG_ICON_TINTABLE) != 0) { - drawable.setTintList(Utils.getColorAccent(mContext)); - } - holder.icon.setImageDrawable(drawable); - holder.title.setText(suggestion.getTitle()); - holder.title.setTypeface(Typeface.create( - mContext.getString(com.android.internal.R.string.config_headlineFontFamily), - Typeface.NORMAL)); - - if (suggestionCount == 1) { - final CharSequence summary = suggestion.getSummary(); - if (!TextUtils.isEmpty(summary)) { - holder.summary.setText(summary); - holder.summary.setVisibility(View.VISIBLE); - } else { - holder.summary.setVisibility(View.GONE); - } - } else { - mConfig.setCardLayout(holder, position); - } - - final View closeButton = holder.itemView.findViewById(R.id.close_button); - if (closeButton != null) { - closeButton.setOnClickListener(v -> { - mSuggestionFeatureProvider.dismissSuggestion( - mContext, mSuggestionControllerMixin, suggestion); - if (mCallback != null) { - mCallback.onSuggestionClosed(suggestion); - } - }); - } - - View clickHandler = holder.itemView; - // If a view with @android:id/primary is defined, use that as the click handler - // instead. - final View primaryAction = holder.itemView.findViewById(android.R.id.primary); - if (primaryAction != null) { - clickHandler = primaryAction; - } - clickHandler.setOnClickListener(v -> { - mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_SETTINGS_SUGGESTION, id); - try { - suggestion.getPendingIntent().send(); - mSuggestionControllerMixin.launchSuggestion(suggestion); - } catch (PendingIntent.CanceledException e) { - Log.w(TAG, "Failed to start suggestion " + suggestion.getTitle()); - } - }); - } - - @Override - public long getItemId(int position) { - return Objects.hash(mSuggestions.get(position).getId()); - } - - @Override - public int getItemViewType(int position) { - final Suggestion suggestion = getSuggestion(position); - if ((suggestion.getFlags() & Suggestion.FLAG_HAS_BUTTON) != 0) { - return R.layout.suggestion_tile_with_button; - } - if (getItemCount() == 1) { - return R.layout.suggestion_tile; - } - return R.layout.suggestion_tile_two_cards; - } - - @Override - public int getItemCount() { - return mSuggestions.size(); - } - - public Suggestion getSuggestion(int position) { - final long itemId = getItemId(position); - if (mSuggestions == null) { - return null; - } - for (Suggestion suggestion : mSuggestions) { - if (Objects.hash(suggestion.getId()) == itemId) { - return suggestion; - } - } - return null; - } - - public void removeSuggestion(Suggestion suggestion) { - final int position = mSuggestions.indexOf(suggestion); - mSuggestions.remove(suggestion); - notifyItemRemoved(position); - } - - @Override - public void onSaveInstanceState(Bundle outState) { - if (mSuggestions != null) { - outState.putParcelableArrayList(STATE_SUGGESTION_LIST, - new ArrayList<>(mSuggestions)); - } - outState.putStringArrayList(STATE_SUGGESTIONS_SHOWN_LOGGED, mSuggestionsShownLogged); - } - - public void setSuggestions(List suggestions) { - mSuggestions = suggestions; - } - - public List getSuggestions() { - return mSuggestions; - } - - @VisibleForTesting - static class CardConfig { - // Card start/end margin - private final int mMarginInner; - private final int mMarginOuter; - private final WindowManager mWindowManager; - - private static CardConfig sConfig; - - private CardConfig(Context context) { - mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); - final Resources res = context.getResources(); - mMarginInner = - res.getDimensionPixelOffset(R.dimen.suggestion_card_inner_margin); - mMarginOuter = - res.getDimensionPixelOffset(R.dimen.suggestion_card_outer_margin); - } - - public static CardConfig get(Context context) { - if (sConfig == null) { - sConfig = new CardConfig(context); - } - return sConfig; - } - - @VisibleForTesting - void setCardLayout(DashboardItemHolder holder, int position) { - final LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( - getWidthForTwoCrads(), LinearLayout.LayoutParams.WRAP_CONTENT); - params.setMarginStart(position == 0 ? mMarginOuter : mMarginInner); - params.setMarginEnd(position != 0 ? mMarginOuter : 0); - holder.itemView.setLayoutParams(params); - } - - private int getWidthForTwoCrads() { - return (getScreenWidth() - mMarginInner - mMarginOuter * 2) / 2; - } - - @VisibleForTesting - int getScreenWidth() { - final DisplayMetrics metrics = new DisplayMetrics(); - mWindowManager.getDefaultDisplay().getMetrics(metrics); - return metrics.widthPixels; - } - } - -} diff --git a/src/com/android/settings/deviceinfo/StorageSettings.java b/src/com/android/settings/deviceinfo/StorageSettings.java index 58188f1aa6d..49d54555b94 100644 --- a/src/com/android/settings/deviceinfo/StorageSettings.java +++ b/src/com/android/settings/deviceinfo/StorageSettings.java @@ -51,7 +51,6 @@ import com.android.settings.R; import com.android.settings.SettingsPreferenceFragment; import com.android.settings.core.SubSettingLauncher; import com.android.settings.core.instrumentation.InstrumentedDialogFragment; -import com.android.settings.dashboard.SummaryLoader; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.Indexable; import com.android.settings.search.SearchIndexableRaw; @@ -61,7 +60,6 @@ import com.android.settingslib.deviceinfo.PrivateStorageInfo; import com.android.settingslib.deviceinfo.StorageManagerVolumeProvider; import com.android.settingslib.search.SearchIndexable; -import java.text.NumberFormat; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -542,41 +540,6 @@ public class StorageSettings extends SettingsPreferenceFragment implements Index } } - private static class SummaryProvider implements SummaryLoader.SummaryProvider { - private final Context mContext; - private final SummaryLoader mLoader; - private final StorageManagerVolumeProvider mStorageManagerVolumeProvider; - - private SummaryProvider(Context context, SummaryLoader loader) { - mContext = context; - mLoader = loader; - final StorageManager storageManager = mContext.getSystemService(StorageManager.class); - mStorageManagerVolumeProvider = new StorageManagerVolumeProvider(storageManager); - } - - @Override - public void setListening(boolean listening) { - if (listening) { - updateSummary(); - } - } - - private void updateSummary() { - // TODO: Register listener. - final NumberFormat percentageFormat = NumberFormat.getPercentInstance(); - final PrivateStorageInfo info = PrivateStorageInfo.getPrivateStorageInfo( - mStorageManagerVolumeProvider); - double privateUsedBytes = info.totalBytes - info.freeBytes; - mLoader.setSummary(this, mContext.getString(R.string.storage_summary, - percentageFormat.format(privateUsedBytes / info.totalBytes), - Formatter.formatFileSize(mContext, info.freeBytes))); - } - } - - - public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY - = (activity, summaryLoader) -> new SummaryProvider(activity, summaryLoader); - /** Enable indexing of searchable data */ public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = new BaseSearchIndexProvider() { diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java index 054c66b69f3..f7c31e58f40 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java +++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java @@ -17,9 +17,7 @@ package com.android.settings.fuelgauge; import static com.android.settings.fuelgauge.BatteryBroadcastReceiver.BatteryUpdateType; -import static com.android.settings.fuelgauge.TopLevelBatteryPreferenceController.getDashboardLabel; -import android.app.Activity; import android.content.Context; import android.os.BatteryStats; import android.os.Bundle; @@ -43,7 +41,6 @@ import com.android.settings.SettingsActivity; import com.android.settings.Utils; import com.android.settings.applications.LayoutPreference; import com.android.settings.core.SubSettingLauncher; -import com.android.settings.dashboard.SummaryLoader; import com.android.settings.fuelgauge.batterytip.BatteryTipLoader; import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController; import com.android.settings.fuelgauge.batterytip.tips.BatteryTip; @@ -389,35 +386,6 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList restartBatteryTipLoader(); } - private static class SummaryProvider implements SummaryLoader.SummaryProvider { - private final Context mContext; - private final SummaryLoader mLoader; - private final BatteryBroadcastReceiver mBatteryBroadcastReceiver; - - private SummaryProvider(Context context, SummaryLoader loader) { - mContext = context; - mLoader = loader; - mBatteryBroadcastReceiver = new BatteryBroadcastReceiver(mContext); - mBatteryBroadcastReceiver.setBatteryChangedListener(type -> { - BatteryInfo.getBatteryInfo(mContext, new BatteryInfo.Callback() { - @Override - public void onBatteryInfoLoaded(BatteryInfo info) { - mLoader.setSummary(SummaryProvider.this, getDashboardLabel(mContext, info)); - } - }, true /* shortString */); - }); - } - - @Override - public void setListening(boolean listening) { - if (listening) { - mBatteryBroadcastReceiver.register(); - } else { - mBatteryBroadcastReceiver.unRegister(); - } - } - } - public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = new BaseSearchIndexProvider() { @@ -429,13 +397,4 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList return Collections.singletonList(sir); } }; - - public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY - = new SummaryLoader.SummaryProviderFactory() { - @Override - public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity, - SummaryLoader summaryLoader) { - return new SummaryProvider(activity, summaryLoader); - } - }; } diff --git a/src/com/android/settings/homepage/conditional/ConditionAdapter.java b/src/com/android/settings/homepage/conditional/ConditionAdapter.java deleted file mode 100644 index a87e4bc3eca..00000000000 --- a/src/com/android/settings/homepage/conditional/ConditionAdapter.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settings.homepage.conditional; - -import android.content.Context; -import android.text.TextUtils; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; - -import androidx.recyclerview.widget.RecyclerView; - -import com.android.internal.logging.nano.MetricsProto; -import com.android.settings.R; -import com.android.settings.dashboard.DashboardAdapter; -import com.android.settings.overlay.FeatureFactory; -import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; - -import java.util.List; - -public class ConditionAdapter extends RecyclerView.Adapter { - - private final Context mContext; - private final MetricsFeatureProvider mMetricsFeatureProvider; - private final ConditionManager mConditionManager; - private final List mConditions; - private final boolean mExpanded; - - public ConditionAdapter(Context context, ConditionManager conditionManager, - List conditions, boolean expanded) { - mContext = context; - mConditionManager = conditionManager; - mConditions = conditions; - mExpanded = expanded; - mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); - - setHasStableIds(true); - } - - @Override - public DashboardAdapter.DashboardItemHolder onCreateViewHolder(ViewGroup parent, int viewType) { - return new DashboardAdapter.DashboardItemHolder(LayoutInflater.from(parent.getContext()) - .inflate(viewType, parent, false)); - } - - @Override - public void onBindViewHolder(DashboardAdapter.DashboardItemHolder holder, int position) { - final ConditionalCard condition = mConditions.get(position); - final boolean isLastItem = position == mConditions.size() - 1; - bindViews(condition, holder, isLastItem); - } - - @Override - public long getItemId(int position) { - return mConditions.get(position).getId(); - } - - @Override - public int getItemViewType(int position) { - return R.layout.condition_tile; - } - - @Override - public int getItemCount() { - if (mExpanded) { - return mConditions.size(); - } - return 0; - } - - private void bindViews(final ConditionalCard condition, - DashboardAdapter.DashboardItemHolder view, boolean isLastItem) { - mMetricsFeatureProvider.visible(mContext, MetricsProto.MetricsEvent.DASHBOARD_SUMMARY, - condition.getMetricsConstant()); - view.itemView.findViewById(R.id.content).setOnClickListener( - v -> { - mMetricsFeatureProvider.action(mContext, - MetricsProto.MetricsEvent.ACTION_SETTINGS_CONDITION_CLICK, - condition.getMetricsConstant()); - mConditionManager.onPrimaryClick(mContext, condition.getId()); - }); - view.icon.setImageDrawable(condition.getIcon()); - view.title.setText(condition.getTitle()); - view.summary.setText(condition.getSummary()); - - setViewVisibility(view.itemView, R.id.divider, !isLastItem); - - final CharSequence action = condition.getActionText(); - final boolean hasButtons = !TextUtils.isEmpty(action); - setViewVisibility(view.itemView, R.id.buttonBar, hasButtons); - - final Button button = view.itemView.findViewById(R.id.first_action); - if (hasButtons) { - button.setVisibility(View.VISIBLE); - button.setText(action); - button.setOnClickListener(v -> { - final Context context = v.getContext(); - mMetricsFeatureProvider.action( - context, MetricsProto.MetricsEvent.ACTION_SETTINGS_CONDITION_BUTTON, - condition.getMetricsConstant()); - mConditionManager.onActionClick(condition.getId()); - }); - } else { - button.setVisibility(View.GONE); - } - - } - - private void setViewVisibility(View containerView, int viewId, boolean visible) { - View view = containerView.findViewById(viewId); - if (view != null) { - view.setVisibility(visible ? View.VISIBLE : View.GONE); - } - } -} diff --git a/src/com/android/settings/network/NetworkDashboardFragment.java b/src/com/android/settings/network/NetworkDashboardFragment.java index 0279cfabc94..9706ba01ec6 100644 --- a/src/com/android/settings/network/NetworkDashboardFragment.java +++ b/src/com/android/settings/network/NetworkDashboardFragment.java @@ -15,29 +15,20 @@ */ package com.android.settings.network; -import static android.provider.Settings.ACTION_DATA_USAGE_SETTINGS; import static com.android.settings.network.MobilePlanPreferenceController .MANAGE_MOBILE_PLAN_DIALOG_ID; -import android.app.Activity; import android.app.Dialog; import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.icu.text.ListFormatter; import android.provider.SearchIndexableResource; -import android.text.BidiFormatter; -import android.text.TextUtils; import android.util.Log; -import androidx.annotation.VisibleForTesting; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.Fragment; import com.android.internal.logging.nano.MetricsProto; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; -import com.android.settings.dashboard.SummaryLoader; import com.android.settings.network.MobilePlanPreferenceController.MobilePlanPreferenceHost; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.wifi.WifiMasterSwitchPreferenceController; @@ -48,7 +39,6 @@ import com.android.settingslib.search.SearchIndexable; import java.util.ArrayList; import java.util.Arrays; -import java.util.function.BooleanSupplier; import java.util.List; @SearchIndexable @@ -153,84 +143,6 @@ public class NetworkDashboardFragment extends DashboardFragment implements return 0; } - // TODO(b/110405144): Remove SummaryProvider - @VisibleForTesting - static class SummaryProvider implements SummaryLoader.SummaryProvider { - - private final Context mContext; - private final SummaryLoader mSummaryLoader; - private final WifiMasterSwitchPreferenceController mWifiPreferenceController; - private final MobileNetworkPreferenceController mMobileNetworkPreferenceController; - private final TetherPreferenceController mTetherPreferenceController; - private final BooleanSupplier mHasDataUsageActivity; - - public SummaryProvider(Context context, SummaryLoader summaryLoader) { - this(context, summaryLoader, - new WifiMasterSwitchPreferenceController(context, null), - new MobileNetworkPreferenceController(context), - new TetherPreferenceController(context, null /* lifecycle */), - () -> { - final Intent intent = new Intent(ACTION_DATA_USAGE_SETTINGS); - final PackageManager pm = context.getPackageManager(); - return intent.resolveActivity(pm) != null; - }); - } - - @VisibleForTesting(otherwise = VisibleForTesting.NONE) - SummaryProvider(Context context, SummaryLoader summaryLoader, - WifiMasterSwitchPreferenceController wifiPreferenceController, - MobileNetworkPreferenceController mobileNetworkPreferenceController, - TetherPreferenceController tetherPreferenceController, - BooleanSupplier hasDataUsageActivity) { - mContext = context; - mSummaryLoader = summaryLoader; - mWifiPreferenceController = wifiPreferenceController; - mMobileNetworkPreferenceController = mobileNetworkPreferenceController; - mTetherPreferenceController = tetherPreferenceController; - mHasDataUsageActivity = hasDataUsageActivity; - } - - - @Override - public void setListening(boolean listening) { - if (listening) { - final String wifiSummary = BidiFormatter.getInstance() - .unicodeWrap(mContext.getString(R.string.wifi_settings_title)); - final String mobileSummary = mContext.getString( - R.string.network_dashboard_summary_mobile); - final String dataUsageSummary = mContext.getString( - R.string.network_dashboard_summary_data_usage); - final String hotspotSummary = mContext.getString( - R.string.network_dashboard_summary_hotspot); - - final List summaries = new ArrayList<>(); - if (mWifiPreferenceController.isAvailable() && !TextUtils.isEmpty(wifiSummary)) { - summaries.add(wifiSummary); - } - if (mMobileNetworkPreferenceController.isAvailable() && !TextUtils.isEmpty(mobileSummary)) { - summaries.add(mobileSummary); - } - if (!TextUtils.isEmpty(dataUsageSummary) && mHasDataUsageActivity.getAsBoolean()) { - summaries.add(dataUsageSummary); - } - if (mTetherPreferenceController.isAvailable() && !TextUtils.isEmpty(hotspotSummary)) { - summaries.add(hotspotSummary); - } - mSummaryLoader.setSummary(this, ListFormatter.getInstance().format(summaries)); - } - } - } - - public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY - = new SummaryLoader.SummaryProviderFactory() { - @Override - public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity, - SummaryLoader summaryLoader) { - return new SummaryProvider(activity, summaryLoader); - } - }; - - public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = new BaseSearchIndexProvider() { @Override diff --git a/src/com/android/settings/security/SecuritySettings.java b/src/com/android/settings/security/SecuritySettings.java index 72dd91b8e67..eb0d6f11c1f 100644 --- a/src/com/android/settings/security/SecuritySettings.java +++ b/src/com/android/settings/security/SecuritySettings.java @@ -18,21 +18,16 @@ package com.android.settings.security; import static com.android.settings.security.EncryptionStatusPreferenceController .PREF_KEY_ENCRYPTION_SECURITY_PAGE; -import android.app.Activity; import android.content.Context; import android.content.Intent; -import android.hardware.face.FaceManager; -import android.hardware.fingerprint.FingerprintManager; import android.provider.SearchIndexableResource; import com.android.internal.logging.nano.MetricsProto; import com.android.settings.R; -import com.android.settings.Utils; import com.android.settings.biometrics.face.FaceStatusPreferenceController; import com.android.settings.biometrics.fingerprint.FingerprintProfileStatusPreferenceController; import com.android.settings.biometrics.fingerprint.FingerprintStatusPreferenceController; import com.android.settings.dashboard.DashboardFragment; -import com.android.settings.dashboard.SummaryLoader; import com.android.settings.enterprise.EnterprisePrivacyPreferenceController; import com.android.settings.location.LocationPreferenceController; import com.android.settings.search.BaseSearchIndexProvider; @@ -166,44 +161,4 @@ public class SecuritySettings extends DashboardFragment { null /* host*/); } }; - - static class SummaryProvider implements SummaryLoader.SummaryProvider { - - private final Context mContext; - private final SummaryLoader mSummaryLoader; - - public SummaryProvider(Context context, SummaryLoader summaryLoader) { - mContext = context; - mSummaryLoader = summaryLoader; - } - - @Override - public void setListening(boolean listening) { - if (listening) { - final FingerprintManager fpm = - Utils.getFingerprintManagerOrNull(mContext); - final FaceManager faceManager = - Utils.getFaceManagerOrNull(mContext); - if (faceManager != null && faceManager.isHardwareDetected()) { - mSummaryLoader.setSummary(this, - mContext.getString(R.string.security_dashboard_summary_face)); - } else if (fpm != null && fpm.isHardwareDetected()) { - mSummaryLoader.setSummary(this, - mContext.getString(R.string.security_dashboard_summary)); - } else { - mSummaryLoader.setSummary(this, mContext.getString( - R.string.security_dashboard_summary_no_fingerprint)); - } - } - } - } - - public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY = - new SummaryLoader.SummaryProviderFactory() { - @Override - public SummaryLoader.SummaryProvider createSummaryProvider(Activity activity, - SummaryLoader summaryLoader) { - return new SummaryProvider(activity, summaryLoader); - } - }; } diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java deleted file mode 100644 index f544f09db97..00000000000 --- a/tests/robotests/src/com/android/settings/dashboard/DashboardAdapterTest.java +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.settings.dashboard; - -import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_TITLE; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.app.PendingIntent; -import android.content.Context; -import android.content.pm.ActivityInfo; -import android.content.res.Resources; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.Icon; -import android.os.Bundle; -import android.service.settings.suggestions.Suggestion; -import android.util.DisplayMetrics; -import android.view.LayoutInflater; -import android.view.View; -import android.view.WindowManager; -import android.widget.TextView; - -import androidx.recyclerview.widget.RecyclerView; - -import com.android.settings.R; -import com.android.settings.SettingsActivity; -import com.android.settings.dashboard.suggestions.SuggestionAdapter; -import com.android.settings.homepage.conditional.ConditionManager; -import com.android.settings.homepage.conditional.ConditionalCard; -import com.android.settings.testutils.FakeFeatureFactory; -import com.android.settings.testutils.SettingsRobolectricTestRunner; -import com.android.settings.testutils.shadow.SettingsShadowResources; -import com.android.settings.widget.RoundedHomepageIcon; -import com.android.settingslib.drawer.CategoryKey; -import com.android.settingslib.drawer.Tile; -import com.android.settingslib.utils.IconCache; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Answers; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.annotation.Config; -import org.robolectric.util.ReflectionHelpers; - -import java.util.ArrayList; -import java.util.List; - -@RunWith(SettingsRobolectricTestRunner.class) -@Config(shadows = SettingsShadowResources.SettingsShadowTheme.class) -public class DashboardAdapterTest { - - @Mock(answer = Answers.RETURNS_DEEP_STUBS) - private SettingsActivity mContext; - @Mock - private ConditionalCard mCondition; - @Mock - private Resources mResources; - @Mock - private WindowManager mWindowManager; - @Mock - private ConditionManager mConditionManager; - - private ActivityInfo mActivityInfo; - private DashboardAdapter mDashboardAdapter; - private List mConditionList; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - FakeFeatureFactory.setupForTest(); - mActivityInfo = new ActivityInfo(); - mActivityInfo.packageName = "pkg"; - mActivityInfo.name = "class"; - mActivityInfo.metaData = new Bundle(); - mActivityInfo.metaData.putString(META_DATA_PREFERENCE_TITLE, "test-title"); - - when(mContext.getSystemService(Context.WINDOW_SERVICE)).thenReturn(mWindowManager); - when(mContext.getResources()).thenReturn(mResources); - when(mResources.getQuantityString(any(int.class), any(int.class), any())).thenReturn(""); - - mConditionList = new ArrayList<>(); - mConditionList.add(mCondition); - mDashboardAdapter = new DashboardAdapter(mContext, null /* savedInstanceState */, - mConditionManager, null /* suggestionControllerMixin */, null /* lifecycle */); - } - - @Test - public void onSuggestionClosed_notOnlySuggestion_updateSuggestionOnly() { - final DashboardAdapter adapter = - spy(new DashboardAdapter(mContext, null /* savedInstanceState */, - mConditionManager, - null /* suggestionControllerMixin */, - null /* lifecycle */)); - final List suggestions = makeSuggestions("pkg1", "pkg2", "pkg3"); - adapter.setSuggestions(suggestions); - - final RecyclerView data = mock(RecyclerView.class); - when(data.getResources()).thenReturn(mResources); - when(data.getContext()).thenReturn(mContext); - when(mResources.getDisplayMetrics()).thenReturn(mock(DisplayMetrics.class)); - final View itemView = mock(View.class); - when(itemView.findViewById(R.id.suggestion_list)).thenReturn(data); - when(itemView.findViewById(android.R.id.summary)).thenReturn(mock(TextView.class)); - when(itemView.findViewById(android.R.id.title)).thenReturn(mock(TextView.class)); - final DashboardAdapter.SuggestionContainerHolder holder = - new DashboardAdapter.SuggestionContainerHolder(itemView); - - adapter.onBindSuggestion(holder, 0); - - reset(adapter); // clear interactions tracking - - final Suggestion suggestionToRemove = suggestions.get(1); - adapter.onSuggestionClosed(suggestionToRemove); - - assertThat(suggestions.size()).isEqualTo(2); - assertThat(suggestions.contains(suggestionToRemove)).isFalse(); - verify(adapter).notifyDashboardDataChanged(any()); - } - - @Test - public void onSuggestionClosed_onlySuggestion_updateDashboardData() { - final DashboardAdapter adapter = - spy(new DashboardAdapter(mContext, null /* savedInstanceState */, - mConditionManager, - null /* suggestionControllerMixin */, null /* lifecycle */)); - final List suggestions = makeSuggestions("pkg1"); - adapter.setSuggestions(suggestions); - final DashboardData dashboardData = adapter.mDashboardData; - reset(adapter); // clear interactions tracking - - adapter.onSuggestionClosed(suggestions.get(0)); - - assertThat(adapter.mDashboardData).isNotEqualTo(dashboardData); - verify(adapter).notifyDashboardDataChanged(any()); - } - - @Test - public void onSuggestionClosed_notInSuggestionList_shouldNotUpdateSuggestionList() { - final DashboardAdapter adapter = - spy(new DashboardAdapter(mContext, null /* savedInstanceState */, - mConditionManager, - null /* suggestionControllerMixin */, null /* lifecycle */)); - final List suggestions = makeSuggestions("pkg1"); - adapter.setSuggestions(suggestions); - - reset(adapter); // clear interactions tracking - - adapter.onSuggestionClosed(mock(Suggestion.class)); - - verify(adapter, never()).setSuggestions(any()); - } - - @Test - public void onBindSuggestion_shouldSetSuggestionAdapterAndNoCrash() { - mDashboardAdapter = new DashboardAdapter(mContext, null /* savedInstanceState */, - mConditionManager, null /* suggestionControllerMixin */, null /* lifecycle */); - final List suggestions = makeSuggestions("pkg1"); - - mDashboardAdapter.setSuggestions(suggestions); - - final RecyclerView data = mock(RecyclerView.class); - when(data.getResources()).thenReturn(mResources); - when(data.getContext()).thenReturn(mContext); - when(mResources.getDisplayMetrics()).thenReturn(mock(DisplayMetrics.class)); - final View itemView = mock(View.class); - when(itemView.findViewById(R.id.suggestion_list)).thenReturn(data); - when(itemView.findViewById(android.R.id.summary)).thenReturn(mock(TextView.class)); - when(itemView.findViewById(android.R.id.title)).thenReturn(mock(TextView.class)); - final DashboardAdapter.SuggestionContainerHolder holder = - new DashboardAdapter.SuggestionContainerHolder(itemView); - - mDashboardAdapter.onBindSuggestion(holder, 0); - - verify(data).setAdapter(any(SuggestionAdapter.class)); - // should not crash - } - - @Test - public void onBindTile_internalTile_shouldNotUseGenericBackgroundIcon() { - final Context context = RuntimeEnvironment.application; - final View view = LayoutInflater.from(context).inflate(R.layout.dashboard_tile, null); - final DashboardAdapter.DashboardItemHolder holder = - new DashboardAdapter.DashboardItemHolder(view); - final Tile tile = spy(new Tile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE)); - doReturn(Icon.createWithResource(context, R.drawable.ic_settings)) - .when(tile).getIcon(context); - final IconCache iconCache = mock(IconCache.class); - when(iconCache.getIcon(tile.getIcon(context))) - .thenReturn(context.getDrawable(R.drawable.ic_settings)); - - mDashboardAdapter = new DashboardAdapter(context, null /* savedInstanceState */, - mConditionManager, null /* suggestionControllerMixin */, null /* lifecycle */); - ReflectionHelpers.setField(mDashboardAdapter, "mCache", iconCache); - mDashboardAdapter.onBindTile(holder, tile); - - verify(iconCache, never()).updateIcon(any(Icon.class), any(Drawable.class)); - } - - @Test - public void onBindTile_externalTile_shouldUpdateIcon() { - final Context context = spy(RuntimeEnvironment.application); - final View view = LayoutInflater.from(context).inflate(R.layout.dashboard_tile, null); - final DashboardAdapter.DashboardItemHolder holder = - new DashboardAdapter.DashboardItemHolder(view); - final Tile tile = spy(new Tile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE)); - final Icon icon = Icon.createWithResource(context, R.drawable.ic_settings); - doReturn(icon).when(tile).getIcon(context); - - final IconCache iconCache = new IconCache(context); - - mDashboardAdapter = new DashboardAdapter(context, null /* savedInstanceState */, - mConditionManager, - null /* suggestionControllerMixin */, null /* lifecycle */); - ReflectionHelpers.setField(mDashboardAdapter, "mCache", iconCache); - - doReturn("another.package").when(context).getPackageName(); - mDashboardAdapter.onBindTile(holder, tile); - - assertThat(iconCache.getIcon(tile.getIcon(context))) - .isInstanceOf(RoundedHomepageIcon.class); - } - - @Test - public void onBindTile_externalTile_usingRoundedHomepageIcon_shouldNotUpdateIcon() { - final Context context = RuntimeEnvironment.application; - final View view = LayoutInflater.from(context).inflate(R.layout.dashboard_tile, null); - final DashboardAdapter.DashboardItemHolder holder = - new DashboardAdapter.DashboardItemHolder(view); - final Tile tile = spy(new Tile(mActivityInfo, CategoryKey.CATEGORY_HOMEPAGE)); - doReturn(mock(Icon.class)).when(tile).getIcon(context); - when(tile.getIcon(context).getResPackage()).thenReturn("another.package"); - - final IconCache iconCache = mock(IconCache.class); - when(iconCache.getIcon(tile.getIcon(context))).thenReturn(mock(RoundedHomepageIcon.class)); - - mDashboardAdapter = new DashboardAdapter(context, null /* savedInstanceState */, - mConditionManager, null /* suggestionControllerMixin */, null /* lifecycle */); - ReflectionHelpers.setField(mDashboardAdapter, "mCache", iconCache); - - mDashboardAdapter.onBindTile(holder, tile); - - verify(iconCache, never()).updateIcon(eq(tile.getIcon(context)), - any(RoundedHomepageIcon.class)); - } - - private List makeSuggestions(String... pkgNames) { - final List suggestions = new ArrayList<>(); - for (String pkgName : pkgNames) { - final Suggestion suggestion = new Suggestion.Builder(pkgName) - .setPendingIntent(mock(PendingIntent.class)) - .build(); - suggestions.add(suggestion); - } - return suggestions; - } -} diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardDataTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardDataTest.java deleted file mode 100644 index 73b1734212b..00000000000 --- a/tests/robotests/src/com/android/settings/dashboard/DashboardDataTest.java +++ /dev/null @@ -1,417 +0,0 @@ -/* - * Copyright (C) 2016 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.settings.dashboard; - -import static com.android.settings.dashboard.DashboardData.STABLE_ID_CONDITION_CONTAINER; -import static com.android.settings.dashboard.DashboardData.STABLE_ID_CONDITION_FOOTER; -import static com.android.settings.dashboard.DashboardData.STABLE_ID_SUGGESTION_CONDITION_DIVIDER; -import static com.android.settings.dashboard.DashboardData.STABLE_ID_SUGGESTION_CONTAINER; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import android.app.PendingIntent; -import android.service.settings.suggestions.Suggestion; - -import androidx.annotation.NonNull; -import androidx.recyclerview.widget.DiffUtil; -import androidx.recyclerview.widget.ListUpdateCallback; - -import com.android.settings.homepage.conditional.AirplaneModeConditionCard; -import com.android.settings.homepage.conditional.ConditionalCard; -import com.android.settings.testutils.SettingsRobolectricTestRunner; -import com.android.settingslib.drawer.CategoryKey; -import com.android.settingslib.drawer.DashboardCategory; -import com.android.settingslib.drawer.Tile; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -@RunWith(SettingsRobolectricTestRunner.class) -public class DashboardDataTest { - - private static final String TEST_SUGGESTION_TITLE = "Use fingerprint"; - private static final int TEST_TILE_ID = 12345; - - private DashboardData mDashboardDataWithOneConditions; - private DashboardData mDashboardDataWithTwoConditions; - private DashboardData mDashboardDataWithNoItems; - private DashboardCategory mDashboardCategory; - @Mock - private Tile mTestCategoryTile; - @Mock - private ConditionalCard mTestCondition; - @Mock - private ConditionalCard mSecondCondition; // condition used to test insert in DiffUtil - private Suggestion mTestSuggestion; - - @Before - public void SetUp() { - MockitoAnnotations.initMocks(this); - - mDashboardCategory = new DashboardCategory(CategoryKey.CATEGORY_HOMEPAGE); - - // Build suggestions - final List suggestions = new ArrayList<>(); - mTestSuggestion = new Suggestion.Builder("pkg") - .setTitle(TEST_SUGGESTION_TITLE) - .setPendingIntent(mock(PendingIntent.class)) - .build(); - suggestions.add(mTestSuggestion); - - // Build oneItemConditions - final List oneItemConditions = new ArrayList<>(); - oneItemConditions.add(mTestCondition); - - // Build twoItemConditions - final List twoItemsConditions = new ArrayList<>(); - twoItemsConditions.add(mTestCondition); - twoItemsConditions.add(mSecondCondition); - - // Build category - when(mTestCategoryTile.getId()).thenReturn(TEST_TILE_ID); - - mDashboardCategory.addTile(mTestCategoryTile); - - // Build DashboardData - mDashboardDataWithOneConditions = new DashboardData.Builder() - .setConditions(oneItemConditions) - .setCategory(mDashboardCategory) - .setSuggestions(suggestions) - .setConditionExpanded(true) - .build(); - - mDashboardDataWithTwoConditions = new DashboardData.Builder() - .setConditions(twoItemsConditions) - .setCategory(mDashboardCategory) - .setSuggestions(suggestions) - .setConditionExpanded(true) - .build(); - - mDashboardDataWithNoItems = new DashboardData.Builder() - .setConditions(null) - .setCategory(null) - .setSuggestions(null) - .build(); - } - - @Test - public void testBuildItemsData_shouldSetstableId() { - final List items = mDashboardDataWithOneConditions.getItemList(); - - // suggestion, separator, condition, footer, 1 tile - assertThat(items).hasSize(5); - - assertThat(items.get(0).id).isEqualTo(STABLE_ID_SUGGESTION_CONTAINER); - assertThat(items.get(1).id).isEqualTo(STABLE_ID_SUGGESTION_CONDITION_DIVIDER); - assertThat(items.get(2).id).isEqualTo(STABLE_ID_CONDITION_CONTAINER); - assertThat(items.get(3).id).isEqualTo(STABLE_ID_CONDITION_FOOTER); - assertThat(items.get(4).id).isEqualTo(TEST_TILE_ID); - } - - @Test - public void testBuildItemsData_containsAllData() { - final Object[] expectedObjects = { - mDashboardDataWithOneConditions.getSuggestions(), - null /* divider */, - mDashboardDataWithOneConditions.getConditions(), - null /* footer */, mTestCategoryTile}; - final int expectedSize = expectedObjects.length; - - assertThat(mDashboardDataWithOneConditions.getItemList()).hasSize(expectedSize); - - for (int i = 0; i < expectedSize; i++) { - final Object item = mDashboardDataWithOneConditions.getItemEntityByPosition(i); - if (item instanceof List) { - assertThat(item).isEqualTo(expectedObjects[i]); - } else if (item instanceof DashboardData.ConditionHeaderData) { - DashboardData.ConditionHeaderData i1 = (DashboardData.ConditionHeaderData) item; - DashboardData.ConditionHeaderData i2 = - (DashboardData.ConditionHeaderData) expectedObjects[i]; - assertThat(i1.title).isEqualTo(i2.title); - assertThat(i1.conditionCount).isEqualTo(i2.conditionCount); - } else { - assertThat(item).isSameAs(expectedObjects[i]); - } - } - } - - @Test - public void testGetPositionByEntity_selfInstance_returnPositionFound() { - final int position = mDashboardDataWithOneConditions - .getPositionByEntity(mDashboardDataWithOneConditions.getConditions()); - assertThat(position).isNotEqualTo(DashboardData.POSITION_NOT_FOUND); - } - - @Test - public void testGetPositionByEntity_notExisted_returnNotFound() { - final ConditionalCard condition = mock(AirplaneModeConditionCard.class); - final int position = mDashboardDataWithOneConditions.getPositionByEntity(condition); - assertThat(position).isEqualTo(DashboardData.POSITION_NOT_FOUND); - } - - @Test - public void testGetPositionByTile_selfInstance_returnPositionFound() { - final int position = mDashboardDataWithOneConditions.getPositionByTile(mTestCategoryTile); - assertThat(position).isNotEqualTo(DashboardData.POSITION_NOT_FOUND); - } - - @Test - public void testGetPositionByTile_equalTitle_returnPositionFound() { - final Tile tile = mock(Tile.class); - when(tile.getId()).thenReturn(TEST_TILE_ID); - - final int position = mDashboardDataWithOneConditions.getPositionByTile(tile); - - assertThat(position).isNotEqualTo(DashboardData.POSITION_NOT_FOUND); - } - - @Test - public void testGetPositionByTile_notExisted_returnNotFound() { - final Tile tile = mock(Tile.class); - when(tile.getId()).thenReturn(123); - final int position = mDashboardDataWithOneConditions.getPositionByTile(tile); - assertThat(position).isEqualTo(DashboardData.POSITION_NOT_FOUND); - } - - @Test - public void testDiffUtil_DataEqual_noResultData() { - List testResultData = new ArrayList<>(); - testDiffUtil(mDashboardDataWithOneConditions, - mDashboardDataWithOneConditions, testResultData); - } - - @Test - public void testDiffUtil_InsertOneCondition_ResultDataOneChanged() { - final List testResultData = new ArrayList<>(); - // Item in position 3 is the condition container containing the list of conditions, which - // gets 1 more item - testResultData.add(new ListUpdateResult.ResultData( - ListUpdateResult.ResultData.TYPE_OPERATION_CHANGE, 2, 1)); - - testDiffUtil(mDashboardDataWithOneConditions, - mDashboardDataWithTwoConditions, testResultData); - } - - @Test - public void testDiffUtil_RemoveOneSuggestion_causeItemRemoveAndChange() { - final List testResultData = new ArrayList<>(); - // removed suggestion and the divider - testResultData.add(new ListUpdateResult.ResultData( - ListUpdateResult.ResultData.TYPE_OPERATION_REMOVE, 0, 2)); - testResultData.add(new ListUpdateResult.ResultData( - ListUpdateResult.ResultData.TYPE_OPERATION_CHANGE, 2, 1)); - // Build DashboardData - final List oneItemConditions = new ArrayList<>(); - - oneItemConditions.add(mTestCondition); - final List suggestions = new ArrayList<>(); - suggestions.add(mTestSuggestion); - - final DashboardData oldData = new DashboardData.Builder() - .setConditions(oneItemConditions) - .setCategory(mDashboardCategory) - .setSuggestions(suggestions) - .setConditionExpanded(false) - .build(); - final DashboardData newData = new DashboardData.Builder() - .setConditions(oneItemConditions) - .setSuggestions(null) - .setCategory(mDashboardCategory) - .setConditionExpanded(false) - .build(); - - testDiffUtil(oldData, newData, testResultData); - } - - @Test - public void testDiffUtil_DeleteAllData_ResultDataOneDeleted() { - final List testResultData = new ArrayList<>(); - testResultData.add(new ListUpdateResult.ResultData( - ListUpdateResult.ResultData.TYPE_OPERATION_REMOVE, 0, 5)); - - testDiffUtil(mDashboardDataWithOneConditions, mDashboardDataWithNoItems, testResultData); - } - - @Test - public void testDiffUtil_typeSuggestedContainer_ResultDataNothingChanged() { - final List testResultData = new ArrayList<>(); - - DashboardData prevData = new DashboardData.Builder() - .setConditions(null) - .setCategory(null) - .setSuggestions(Collections.singletonList(mTestSuggestion)) - .build(); - DashboardData currentData = new DashboardData.Builder() - .setConditions(null) - .setCategory(null) - .setSuggestions(Collections.singletonList(mTestSuggestion)) - .build(); - testDiffUtil(prevData, currentData, testResultData); - } - - /** - * Test when using the - * {@link com.android.settings.dashboard.DashboardData.ItemsDataDiffCallback} - * to transfer List from {@paramref baseDashboardData} to {@paramref diffDashboardData}, - * whether - * the transform data result is equals to {@paramref testResultData} - *

- * The steps are described below: - * 1. Calculate a {@link androidx.recyclerview.widget.DiffUtil.DiffResult} from - * {@paramref baseDashboardData} to {@paramref diffDashboardData} - *

- * 2. Dispatch the {@link androidx.recyclerview.widget.DiffUtil.DiffResult} calculated from step - * 1 - * into {@link ListUpdateResult} - *

- * 3. Get result data(a.k.a. baseResultData) from {@link ListUpdateResult} and compare it to - * {@paramref testResultData} - *

- * Because baseResultData and {@paramref testResultData} don't have sequence. When do the - * comparison, we will sort them first and then compare the inside data from them one by one. - */ - private void testDiffUtil(DashboardData baseDashboardData, DashboardData diffDashboardData, - List testResultData) { - final DiffUtil.DiffResult diffUtilResult = DiffUtil.calculateDiff( - new DashboardData.ItemsDataDiffCallback( - baseDashboardData.getItemList(), diffDashboardData.getItemList())); - - // Dispatch to listUpdateResult, then listUpdateResult will have result data - final ListUpdateResult listUpdateResult = new ListUpdateResult(); - diffUtilResult.dispatchUpdatesTo(listUpdateResult); - - final List baseResultData = listUpdateResult.getResultData(); - assertThat(testResultData.size()).isEqualTo(baseResultData.size()); - - // Sort them so we can compare them one by one using a for loop - Collections.sort(baseResultData); - Collections.sort(testResultData); - final int size = baseResultData.size(); - for (int i = 0; i < size; i++) { - // Refer to equals method in ResultData - assertThat(baseResultData.get(i)).isEqualTo(testResultData.get(i)); - } - } - - /** - * This class contains the result about how the changes made to convert one - * list to another list. It implements ListUpdateCallback to record the result data. - */ - private static class ListUpdateResult implements ListUpdateCallback { - final private List mResultData; - - public ListUpdateResult() { - mResultData = new ArrayList<>(); - } - - private List getResultData() { - return mResultData; - } - - @Override - public void onInserted(int position, int count) { - mResultData.add(new ResultData(ResultData.TYPE_OPERATION_INSERT, position, count)); - } - - @Override - public void onRemoved(int position, int count) { - mResultData.add(new ResultData(ResultData.TYPE_OPERATION_REMOVE, position, count)); - } - - @Override - public void onMoved(int fromPosition, int toPosition) { - mResultData.add( - new ResultData(ResultData.TYPE_OPERATION_MOVE, fromPosition, toPosition)); - } - - @Override - public void onChanged(int position, int count, Object payload) { - mResultData.add(new ResultData(ResultData.TYPE_OPERATION_CHANGE, position, count)); - } - - /** - * This class contains general type and field to record the operation data generated - * in {@link ListUpdateCallback}. Please refer to {@link ListUpdateCallback} for more info. - *

- * The following are examples about the data stored in this class: - *

- * "The data starts from position(arg1) with count number(arg2) is changed(operation)" - * or "The data is moved(operation) from position1(arg1) to position2(arg2)" - */ - private static class ResultData implements Comparable { - - private static final int TYPE_OPERATION_INSERT = 0; - private static final int TYPE_OPERATION_REMOVE = 1; - private static final int TYPE_OPERATION_MOVE = 2; - private static final int TYPE_OPERATION_CHANGE = 3; - - private final int operation; - private final int arg1; - private final int arg2; - - private ResultData(int operation, int arg1, int arg2) { - this.operation = operation; - this.arg1 = arg1; - this.arg2 = arg2; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (!(obj instanceof ResultData)) { - return false; - } - - ResultData targetData = (ResultData) obj; - - return operation == targetData.operation && arg1 == targetData.arg1 - && arg2 == targetData.arg2; - } - - @Override - public int compareTo(@NonNull ResultData resultData) { - if (this.operation != resultData.operation) { - return operation - resultData.operation; - } - - if (arg1 != resultData.arg1) { - return arg1 - resultData.arg1; - } - - return arg2 - resultData.arg2; - } - - @Override - public String toString() { - return "op:" + operation + ",arg1:" + arg1 + ",arg2:" + arg2; - } - } - } -} diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardItemAnimatorTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardItemAnimatorTest.java deleted file mode 100644 index 646643be913..00000000000 --- a/tests/robotests/src/com/android/settings/dashboard/DashboardItemAnimatorTest.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2016 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.settings.dashboard; - -import static com.google.common.truth.Truth.assertThat; - -import android.content.pm.ActivityInfo; -import android.view.View; -import android.widget.TextView; - -import androidx.recyclerview.widget.RecyclerView; - -import com.android.settings.testutils.SettingsRobolectricTestRunner; -import com.android.settingslib.drawer.CategoryKey; -import com.android.settingslib.drawer.Tile; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RuntimeEnvironment; - -@RunWith(SettingsRobolectricTestRunner.class) -public class DashboardItemAnimatorTest { - - private DashboardItemAnimator mDashboardItemAnimator; - private ViewHolder mViewHolder; - - @Before - public void SetUp() { - mDashboardItemAnimator = new DashboardItemAnimator(); - mViewHolder = new ViewHolder(new TextView(RuntimeEnvironment.application)); - final ActivityInfo activityInfo = new ActivityInfo(); - activityInfo.packageName = "pkg"; - activityInfo.name = "class"; - mViewHolder.itemView.setTag(new Tile(activityInfo, CategoryKey.CATEGORY_HOMEPAGE)); - } - - @Test - public void testAnimateChange_NoPositionChange_NoPendingAnimation() { - final boolean hasPendingAnimation = - mDashboardItemAnimator.animateChange(mViewHolder, mViewHolder, 0, 1, 0, 1); - assertThat(hasPendingAnimation).isFalse(); - } - - @Test - public void testAnimateChange_HasPositionChange_HasPendingAnimation() { - final boolean hasPendingAnimation = - mDashboardItemAnimator.animateChange(mViewHolder, mViewHolder, 0, 0, 1, 1); - assertThat(hasPendingAnimation).isTrue(); - } - - @Test - public void testAnimateChange_HasRunningAnimationWhileNoPositionChange_NoPendingAnimation() { - // Set pending move animations - mDashboardItemAnimator.animateMove(mViewHolder, 0, 0, 1, 1); - - final boolean hasPendingAnimation = - mDashboardItemAnimator.animateChange(mViewHolder, mViewHolder, 0, 1, 0, 1); - assertThat(hasPendingAnimation).isFalse(); - } - - // Sample viewholder to use for test - static final class ViewHolder extends RecyclerView.ViewHolder { - - ViewHolder(View itemView) { - super(itemView); - } - } -} diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardSummaryTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardSummaryTest.java deleted file mode 100644 index a4fba72f29b..00000000000 --- a/tests/robotests/src/com/android/settings/dashboard/DashboardSummaryTest.java +++ /dev/null @@ -1,185 +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 com.android.settings.dashboard; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.ArgumentMatchers.nullable; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.content.Context; - -import androidx.fragment.app.FragmentActivity; -import androidx.recyclerview.widget.LinearLayoutManager; - -import com.android.settings.homepage.conditional.ConditionManager; -import com.android.settings.homepage.conditional.FocusRecyclerView; -import com.android.settings.testutils.FakeFeatureFactory; -import com.android.settings.testutils.SettingsRobolectricTestRunner; -import com.android.settingslib.drawer.CategoryKey; -import com.android.settingslib.drawer.DashboardCategory; -import com.android.settingslib.suggestions.SuggestionControllerMixinCompat; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.util.ReflectionHelpers; - -@RunWith(SettingsRobolectricTestRunner.class) -public class DashboardSummaryTest { - - @Mock - private DashboardAdapter mAdapter; - @Mock - private DashboardFeatureProvider mDashboardFeatureProvider; - @Mock - private FocusRecyclerView mDashboard; - @Mock - private LinearLayoutManager mLayoutManager; - @Mock - private ConditionManager mConditionManager; - @Mock - private SummaryLoader mSummaryLoader; - @Mock - private SuggestionControllerMixinCompat mSuggestionControllerMixin; - - private Context mContext; - private DashboardSummary mSummary; - private FakeFeatureFactory mFeatureFactory; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mFeatureFactory = FakeFeatureFactory.setupForTest(); - mContext = RuntimeEnvironment.application; - mSummary = spy(new DashboardSummary()); - ReflectionHelpers.setField(mSummary, "mAdapter", mAdapter); - ReflectionHelpers.setField(mSummary, "mDashboardFeatureProvider", - mDashboardFeatureProvider); - ReflectionHelpers.setField(mSummary, "mDashboard", mDashboard); - ReflectionHelpers.setField(mSummary, "mLayoutManager", mLayoutManager); - ReflectionHelpers.setField(mSummary, "mConditionManager", mConditionManager); - ReflectionHelpers.setField(mSummary, "mSummaryLoader", mSummaryLoader); - } - - @Test - public void onAttach_suggestionDisabled_shouldNotStartSuggestionControllerMixin() { - when(mFeatureFactory.suggestionsFeatureProvider.isSuggestionEnabled(any(Context.class))) - .thenReturn(false); - - mSummary.onAttach(mContext); - final SuggestionControllerMixinCompat mixin = ReflectionHelpers - .getField(mSummary, "mSuggestionControllerMixin"); - assertThat(mixin).isNull(); - } - - @Test - public void onAttach_suggestionEnabled_shouldStartSuggestionControllerMixin() { - when(mFeatureFactory.suggestionsFeatureProvider.isSuggestionEnabled(any(Context.class))) - .thenReturn(true); - - mSummary.onAttach(mContext); - final SuggestionControllerMixinCompat mixin = ReflectionHelpers - .getField(mSummary, "mSuggestionControllerMixin"); - assertThat(mixin).isNotNull(); - } - - @Test - public void updateCategory_shouldGetCategoryFromFeatureProvider() { - ReflectionHelpers.setField(mSummary, "mSuggestionControllerMixin", - mSuggestionControllerMixin); - - when(mSuggestionControllerMixin.isSuggestionLoaded()).thenReturn(true); - doReturn(mock(FragmentActivity.class)).when(mSummary).getActivity(); - mSummary.onAttach(mContext); - mSummary.updateCategory(); - - verify(mSummaryLoader).updateSummaryToCache(nullable(DashboardCategory.class)); - verify(mDashboardFeatureProvider).getTilesForCategory(CategoryKey.CATEGORY_HOMEPAGE); - verify(mAdapter).setCategory(any()); - } - - @Test - public void updateCategory_shouldGetCategoryFromFeatureProvider_evenIfSuggestionDisabled() { - when(mFeatureFactory.suggestionsFeatureProvider.isSuggestionEnabled(any(Context.class))) - .thenReturn(false); - - doReturn(mock(FragmentActivity.class)).when(mSummary).getActivity(); - mSummary.onAttach(mContext); - mSummary.updateCategory(); - - verify(mSummaryLoader).updateSummaryToCache(nullable(DashboardCategory.class)); - verify(mDashboardFeatureProvider).getTilesForCategory(CategoryKey.CATEGORY_HOMEPAGE); - verify(mAdapter).setCategory(any()); - } - - @Test - public void onConditionChanged_PositionAtTop_ScrollToTop() { - when(mLayoutManager.findFirstCompletelyVisibleItemPosition()).thenReturn(1); - mSummary.onConditionsChanged(); - mSummary.onConditionsChanged(); - verify(mDashboard).scrollToPosition(0); - } - - @Test - public void onConditionChanged_PositionNotTop_RemainPosition() { - when(mLayoutManager.findFirstCompletelyVisibleItemPosition()).thenReturn(2); - mSummary.onConditionsChanged(); - mSummary.onConditionsChanged(); - verify(mDashboard, never()).scrollToPosition(0); - } - - @Test - public void onConditionChanged_firstCall_shouldIgnore() { - mSummary.onConditionsChanged(); - verify(mAdapter, never()).setConditions(any()); - } - - @Test - public void onConditionChanged_secondCall_shouldSetConditionsOnAdapter() { - mSummary.onConditionsChanged(); - mSummary.onConditionsChanged(); - verify(mAdapter).setConditions(any()); - } - - @Test - public void onCategoryChanged_noRebuildOnFirstCall() { - doReturn(mock(FragmentActivity.class)).when(mSummary).getActivity(); - doNothing().when(mSummary).rebuildUI(); - mSummary.onCategoriesChanged(); - verify(mSummary, never()).rebuildUI(); - } - - @Test - public void onCategoryChanged_rebuildOnSecondCall() { - doReturn(mock(FragmentActivity.class)).when(mSummary).getActivity(); - doNothing().when(mSummary).rebuildUI(); - mSummary.onCategoriesChanged(); - mSummary.onCategoriesChanged(); - verify(mSummary).rebuildUI(); - } -} \ No newline at end of file diff --git a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionAdapterTest.java b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionAdapterTest.java deleted file mode 100644 index a48264780ce..00000000000 --- a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionAdapterTest.java +++ /dev/null @@ -1,345 +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 com.android.settings.dashboard.suggestions; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.app.PendingIntent; -import android.content.Context; -import android.content.res.ColorStateList; -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.Icon; -import android.service.settings.suggestions.Suggestion; -import android.view.LayoutInflater; -import android.view.View; -import android.view.WindowManager; -import android.widget.FrameLayout; -import android.widget.LinearLayout; - -import com.android.internal.logging.nano.MetricsProto; -import com.android.settings.R; -import com.android.settings.SettingsActivity; -import com.android.settings.dashboard.DashboardAdapter; -import com.android.settings.testutils.FakeFeatureFactory; -import com.android.settings.testutils.SettingsRobolectricTestRunner; -import com.android.settings.testutils.shadow.ShadowCardView; -import com.android.settingslib.Utils; -import com.android.settingslib.suggestions.SuggestionControllerMixinCompat; -import com.android.settingslib.utils.IconCache; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Answers; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.annotation.Config; -import org.robolectric.util.ReflectionHelpers; - -import java.util.ArrayList; -import java.util.List; - -@RunWith(SettingsRobolectricTestRunner.class) -@Config(shadows = ShadowCardView.class) -public class SuggestionAdapterTest { - - @Mock(answer = Answers.RETURNS_DEEP_STUBS) - private SettingsActivity mActivity; - @Mock - private SuggestionControllerMixinCompat mSuggestionControllerMixin; - @Mock - private Resources mResources; - @Mock - private WindowManager mWindowManager; - - private FakeFeatureFactory mFeatureFactory; - private Context mContext; - private SuggestionAdapter mSuggestionAdapter; - private DashboardAdapter.DashboardItemHolder mSuggestionHolder; - private List mOneSuggestion; - private List mTwoSuggestions; - private SuggestionAdapter.CardConfig mConfig; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mContext = spy(RuntimeEnvironment.application); - when(mActivity.getSystemService(Context.WINDOW_SERVICE)).thenReturn(mWindowManager); - when(mActivity.getResources()).thenReturn(mResources); - when(mResources.getDimensionPixelOffset(R.dimen.suggestion_card_inner_margin)) - .thenReturn(10); - when(mResources.getDimensionPixelOffset(R.dimen.suggestion_card_outer_margin)) - .thenReturn(20); - mConfig = spy(SuggestionAdapter.CardConfig.get(mActivity)); - - mFeatureFactory = FakeFeatureFactory.setupForTest(); - - final Suggestion suggestion1 = new Suggestion.Builder("id1") - .setTitle("Test suggestion 1") - .build(); - final Suggestion suggestion2 = new Suggestion.Builder("id2") - .setTitle("Test suggestion 2") - .build(); - mOneSuggestion = new ArrayList<>(); - mOneSuggestion.add(suggestion1); - mTwoSuggestions = new ArrayList<>(); - mTwoSuggestions.add(suggestion1); - mTwoSuggestions.add(suggestion2); - } - - @Test - public void getItemCount_shouldReturnListSize() { - mSuggestionAdapter = new SuggestionAdapter(mContext, mSuggestionControllerMixin, - null /* savedInstanceState */, null /* callback */, null /* lifecycle */); - mSuggestionAdapter.setSuggestions(mOneSuggestion); - assertThat(mSuggestionAdapter.getItemCount()).isEqualTo(1); - - mSuggestionAdapter.setSuggestions(mTwoSuggestions); - assertThat(mSuggestionAdapter.getItemCount()).isEqualTo(2); - } - - @Test - public void getItemViewType_shouldReturnSuggestionTile() { - mSuggestionAdapter = new SuggestionAdapter(mContext, mSuggestionControllerMixin, - null /* savedInstanceState */, null /* callback */, null /* lifecycle */); - mSuggestionAdapter.setSuggestions(mOneSuggestion); - assertThat(mSuggestionAdapter.getItemViewType(0)) - .isEqualTo(R.layout.suggestion_tile); - } - - @Test - public void getItemType_hasButton_shouldReturnSuggestionWithButton() { - final List suggestions = new ArrayList<>(); - suggestions.add(new Suggestion.Builder("id") - .setFlags(Suggestion.FLAG_HAS_BUTTON) - .setTitle("123") - .setSummary("456") - .build()); - mSuggestionAdapter = new SuggestionAdapter(mContext, mSuggestionControllerMixin, - null /* savedInstanceState */, null /* callback */, null /* lifecycle */); - mSuggestionAdapter.setSuggestions(suggestions); - - assertThat(mSuggestionAdapter.getItemViewType(0)) - .isEqualTo(R.layout.suggestion_tile_with_button); - } - - @Test - public void onBindViewHolder_shouldLog() { - final View view = spy(LayoutInflater.from(mContext).inflate( - R.layout.suggestion_tile, new LinearLayout(mContext), true)); - mSuggestionHolder = new DashboardAdapter.DashboardItemHolder(view); - mSuggestionAdapter = new SuggestionAdapter(mContext, mSuggestionControllerMixin, - null /* savedInstanceState */, null /* callback */, null /* lifecycle */); - mSuggestionAdapter.setSuggestions(mOneSuggestion); - doReturn("sans").when(mContext).getString(anyInt()); - - // Bind twice - mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0); - mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0); - - // Log once - verify(mFeatureFactory.metricsFeatureProvider).action( - mContext, MetricsProto.MetricsEvent.ACTION_SHOW_SETTINGS_SUGGESTION, - mOneSuggestion.get(0).getId()); - } - - @Test - public void onBindViewHolder_itemViewShouldHandleClick() - throws PendingIntent.CanceledException { - final List suggestions = makeSuggestions("pkg1"); - setupSuggestions(mActivity, suggestions); - - mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0); - mSuggestionHolder.itemView.performClick(); - - verify(mSuggestionControllerMixin).launchSuggestion(suggestions.get(0)); - verify(suggestions.get(0).getPendingIntent()).send(); - } - - @Test - public void onBindViewHolder_hasButton_buttonShouldHandleClick() - throws PendingIntent.CanceledException { - final List suggestions = new ArrayList<>(); - final PendingIntent pendingIntent = mock(PendingIntent.class); - suggestions.add(new Suggestion.Builder("id") - .setFlags(Suggestion.FLAG_HAS_BUTTON) - .setTitle("123") - .setSummary("456") - .setPendingIntent(pendingIntent) - .build()); - mSuggestionAdapter = new SuggestionAdapter(mContext, mSuggestionControllerMixin, - null /* savedInstanceState */, null /* callback */, null /* lifecycle */); - mSuggestionAdapter.setSuggestions(suggestions); - mSuggestionHolder = mSuggestionAdapter.onCreateViewHolder( - new FrameLayout(RuntimeEnvironment.application), - mSuggestionAdapter.getItemViewType(0)); - doReturn("sans").when(mContext).getString(anyInt()); - - mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0); - mSuggestionHolder.itemView.findViewById(android.R.id.primary).performClick(); - - verify(mSuggestionControllerMixin).launchSuggestion(suggestions.get(0)); - verify(pendingIntent).send(); - } - - @Test - public void getSuggestions_shouldReturnSuggestionWhenMatch() { - final List suggestions = makeSuggestions("pkg1"); - setupSuggestions(mActivity, suggestions); - - assertThat(mSuggestionAdapter.getSuggestion(0)).isNotNull(); - } - - @Test - public void onBindViewHolder_closeButtonShouldHandleClick() - throws PendingIntent.CanceledException { - final List suggestions = makeSuggestions("pkg1"); - final SuggestionAdapter.Callback callback = mock(SuggestionAdapter.Callback.class); - mSuggestionAdapter = new SuggestionAdapter(mActivity, mSuggestionControllerMixin, - null /* savedInstanceState */, callback, null /* lifecycle */); - mSuggestionAdapter.setSuggestions(suggestions); - mSuggestionHolder = mSuggestionAdapter.onCreateViewHolder( - new FrameLayout(RuntimeEnvironment.application), - mSuggestionAdapter.getItemViewType(0)); - - mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0); - mSuggestionHolder.itemView.findViewById(R.id.close_button).performClick(); - - final Suggestion suggestion = suggestions.get(0); - verify(mFeatureFactory.suggestionsFeatureProvider).dismissSuggestion( - mActivity, mSuggestionControllerMixin, suggestion); - verify(callback).onSuggestionClosed(suggestion); - } - - @Test - public void onBindViewHolder_iconNotTintable_shouldNotTintIcon() - throws PendingIntent.CanceledException { - final Icon icon = mock(Icon.class); - final Suggestion suggestion = new Suggestion.Builder("pkg1") - .setPendingIntent(mock(PendingIntent.class)) - .setIcon(icon) - .build(); - final List suggestions = new ArrayList<>(); - suggestions.add(suggestion); - mSuggestionAdapter = new SuggestionAdapter(mActivity, mSuggestionControllerMixin, - null /* savedInstanceState */, null /* callback */, null /* lifecycle */); - mSuggestionAdapter.setSuggestions(suggestions); - mSuggestionHolder = mSuggestionAdapter.onCreateViewHolder( - new FrameLayout(RuntimeEnvironment.application), - mSuggestionAdapter.getItemViewType(0)); - IconCache cache = mock(IconCache.class); - final Drawable drawable = mock(Drawable.class); - when(cache.getIcon(icon)).thenReturn(drawable); - ReflectionHelpers.setField(mSuggestionAdapter, "mCache", cache); - - mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0); - - verify(drawable, never()).setTint(anyInt()); - } - - @Test - public void onBindViewHolder_iconTintable_shouldTintIcon() - throws PendingIntent.CanceledException { - final Icon icon = mock(Icon.class); - final int FLAG_ICON_TINTABLE = 1 << 1; - final Suggestion suggestion = new Suggestion.Builder("pkg1") - .setPendingIntent(mock(PendingIntent.class)) - .setIcon(icon) - .setFlags(FLAG_ICON_TINTABLE) - .build(); - final List suggestions = new ArrayList<>(); - suggestions.add(suggestion); - mSuggestionAdapter = new SuggestionAdapter(mActivity, mSuggestionControllerMixin, - null /* savedInstanceState */, null /* callback */, null /* lifecycle */); - mSuggestionAdapter.setSuggestions(suggestions); - mSuggestionHolder = mSuggestionAdapter.onCreateViewHolder( - new FrameLayout(RuntimeEnvironment.application), - mSuggestionAdapter.getItemViewType(0)); - IconCache cache = mock(IconCache.class); - final Drawable drawable = mock(Drawable.class); - when(cache.getIcon(icon)).thenReturn(drawable); - ReflectionHelpers.setField(mSuggestionAdapter, "mCache", cache); - TypedArray typedArray = mock(TypedArray.class); - final ColorStateList colorAccentState = Utils.getColorAccent(mContext); - when(mActivity.obtainStyledAttributes(any())).thenReturn(typedArray); - when(typedArray.getColorStateList(anyInt())).thenReturn(colorAccentState); - - mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0); - - verify(drawable).setTintList(colorAccentState); - } - - @Test - public void onBindViewHolder_closeButtonShouldHaveContentDescription() - throws PendingIntent.CanceledException { - final List suggestions = makeSuggestions("pkg1"); - setupSuggestions(mActivity, suggestions); - - mSuggestionAdapter.onBindViewHolder(mSuggestionHolder, 0); - - assertThat( - mSuggestionHolder.itemView.findViewById(R.id.close_button).getContentDescription()) - .isNotNull(); - } - - @Test - public void setCardLayout_twoCards_shouldSetCardWidthToHalfScreenMinusPadding() { - final List suggestions = makeSuggestions("pkg1"); - setupSuggestions(mContext, suggestions); - doReturn(200).when(mConfig).getScreenWidth(); - - mConfig.setCardLayout(mSuggestionHolder, 0); - - /* - * card width = (screen width - left margin - inner margin - right margin) / 2 - * = (200 - 20 - 10 - 20) / 2 - * = 75 - */ - assertThat(mSuggestionHolder.itemView.getLayoutParams().width).isEqualTo(75); - } - - private void setupSuggestions(Context context, List suggestions) { - mSuggestionAdapter = new SuggestionAdapter(context, mSuggestionControllerMixin, - null /* savedInstanceState */, null /* callback */, null /* lifecycle */); - mSuggestionAdapter.setSuggestions(suggestions); - mSuggestionHolder = mSuggestionAdapter.onCreateViewHolder( - new FrameLayout(RuntimeEnvironment.application), - mSuggestionAdapter.getItemViewType(0)); - } - - private List makeSuggestions(String... pkgNames) { - final List suggestions = new ArrayList<>(); - for (String pkgName : pkgNames) { - final Suggestion suggestion = new Suggestion.Builder(pkgName) - .setPendingIntent(mock(PendingIntent.class)) - .build(); - suggestions.add(suggestion); - } - return suggestions; - } -} diff --git a/tests/robotests/src/com/android/settings/homepage/conditional/ConditionAdapterTest.java b/tests/robotests/src/com/android/settings/homepage/conditional/ConditionAdapterTest.java deleted file mode 100644 index 4d154da682a..00000000000 --- a/tests/robotests/src/com/android/settings/homepage/conditional/ConditionAdapterTest.java +++ /dev/null @@ -1,121 +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 com.android.settings.homepage.conditional; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.LinearLayout; - -import com.android.settings.R; -import com.android.settings.dashboard.DashboardAdapter; -import com.android.settings.testutils.SettingsRobolectricTestRunner; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.RuntimeEnvironment; - -import java.util.ArrayList; -import java.util.List; - -@RunWith(SettingsRobolectricTestRunner.class) -public class ConditionAdapterTest { - - @Mock - private ConditionalCard mCondition1; - @Mock - private ConditionalCard mCondition2; - @Mock - private ConditionManager mConditionManager; - - private Context mContext; - private ConditionAdapter mConditionAdapter; - private List mOneCondition; - private List mTwoConditions; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mContext = RuntimeEnvironment.application; - final CharSequence action = "action"; - when(mCondition1.getActionText()).thenReturn(action); - mOneCondition = new ArrayList<>(); - mOneCondition.add(mCondition1); - mTwoConditions = new ArrayList<>(); - mTwoConditions.add(mCondition1); - mTwoConditions.add(mCondition2); - } - - @Test - public void getItemCount_notExpanded_shouldReturn0() { - mConditionAdapter = new ConditionAdapter(mContext, mConditionManager, mOneCondition, false); - assertThat(mConditionAdapter.getItemCount()).isEqualTo(0); - } - - @Test - public void getItemCount_expanded_shouldReturnListSize() { - mConditionAdapter = new ConditionAdapter(mContext, mConditionManager, mOneCondition, true); - assertThat(mConditionAdapter.getItemCount()).isEqualTo(1); - - mConditionAdapter = new ConditionAdapter(mContext, mConditionManager, mTwoConditions, true); - assertThat(mConditionAdapter.getItemCount()).isEqualTo(2); - } - - @Test - public void getItemViewType_shouldReturnConditionTile() { - mConditionAdapter = new ConditionAdapter(mContext, mConditionManager, mTwoConditions, true); - assertThat(mConditionAdapter.getItemViewType(0)).isEqualTo(R.layout.condition_tile); - } - - @Test - public void onBindViewHolder_shouldSetListener() { - final View view = LayoutInflater.from(mContext) - .inflate(R.layout.condition_tile, new LinearLayout(mContext), true); - final DashboardAdapter.DashboardItemHolder viewHolder = - new DashboardAdapter.DashboardItemHolder(view); - mConditionAdapter = new ConditionAdapter(mContext, mConditionManager, mOneCondition, true); - - mConditionAdapter.onBindViewHolder(viewHolder, 0); - final View card = view.findViewById(R.id.content); - assertThat(card).isNotNull(); - assertThat(card.hasOnClickListeners()).isTrue(); - } - - @Test - public void viewClick_shouldInvokeConditionPrimaryClick() { - final View view = LayoutInflater.from(mContext) - .inflate(R.layout.condition_tile, new LinearLayout(mContext), true); - final DashboardAdapter.DashboardItemHolder viewHolder = - new DashboardAdapter.DashboardItemHolder(view); - mConditionAdapter = new ConditionAdapter(mContext, mConditionManager, mOneCondition, true); - - mConditionAdapter.onBindViewHolder(viewHolder, 0); - final View card = view.findViewById(R.id.content); - assertThat(card).isNotNull(); - card.performClick(); - verify(mConditionManager).onPrimaryClick(any(Context.class), anyLong()); - } -} diff --git a/tests/robotests/src/com/android/settings/network/NetworkDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/network/NetworkDashboardFragmentTest.java index 469a5372738..e0370a49fd9 100644 --- a/tests/robotests/src/com/android/settings/network/NetworkDashboardFragmentTest.java +++ b/tests/robotests/src/com/android/settings/network/NetworkDashboardFragmentTest.java @@ -17,17 +17,10 @@ package com.android.settings.network; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; - import android.content.Context; import android.provider.SearchIndexableResource; -import com.android.settings.dashboard.SummaryLoader; import com.android.settings.testutils.SettingsRobolectricTestRunner; -import com.android.settings.wifi.WifiMasterSwitchPreferenceController; import com.android.settingslib.drawer.CategoryKey; import org.junit.Before; @@ -65,90 +58,4 @@ public class NetworkDashboardFragmentTest { assertThat(indexRes).hasSize(1); assertThat(indexRes.get(0).xmlResId).isEqualTo(mFragment.getPreferenceScreenResId()); } - - @Test - public void summaryProviderSetListening_hasMobileAndHotspot_shouldReturnMobileSummary() { - final WifiMasterSwitchPreferenceController wifiPreferenceController = - mock(WifiMasterSwitchPreferenceController.class); - final MobileNetworkPreferenceController mobileNetworkPreferenceController = - mock(MobileNetworkPreferenceController.class); - final TetherPreferenceController tetherPreferenceController = - mock(TetherPreferenceController.class); - - final SummaryLoader summaryLoader = mock(SummaryLoader.class); - final SummaryLoader.SummaryProvider provider = - new NetworkDashboardFragment.SummaryProvider(mContext, summaryLoader, - wifiPreferenceController, mobileNetworkPreferenceController, - tetherPreferenceController, () -> true); - - provider.setListening(false); - - verifyZeroInteractions(summaryLoader); - - when(wifiPreferenceController.isAvailable()).thenReturn(true); - when(mobileNetworkPreferenceController.isAvailable()).thenReturn(true); - when(tetherPreferenceController.isAvailable()).thenReturn(true); - - provider.setListening(true); - - verify(summaryLoader).setSummary(provider, "Wi\u2011Fi, mobile, data usage, and hotspot"); - } - - @Test - public void summaryProviderSetListening_noMobileOrHotspot_shouldReturnSimpleSummary() { - final WifiMasterSwitchPreferenceController wifiPreferenceController = - mock(WifiMasterSwitchPreferenceController.class); - final MobileNetworkPreferenceController mobileNetworkPreferenceController = - mock(MobileNetworkPreferenceController.class); - final TetherPreferenceController tetherPreferenceController = - mock(TetherPreferenceController.class); - - final SummaryLoader summaryLoader = mock(SummaryLoader.class); - final SummaryLoader.SummaryProvider provider = - new NetworkDashboardFragment.SummaryProvider(mContext, summaryLoader, - wifiPreferenceController, mobileNetworkPreferenceController, - tetherPreferenceController, () -> true); - - provider.setListening(false); - - verifyZeroInteractions(summaryLoader); - - when(wifiPreferenceController.isAvailable()).thenReturn(true); - when(mobileNetworkPreferenceController.isAvailable()).thenReturn(false); - when(tetherPreferenceController.isAvailable()).thenReturn(false); - - provider.setListening(true); - - verify(summaryLoader).setSummary(provider, "Wi\u2011Fi and data usage"); - } - - @Test - public void summaryProviderSetListening_noDataUsageActivity_shouldReturnNoDataUsageSummary() { - final WifiMasterSwitchPreferenceController wifiPreferenceController = - mock(WifiMasterSwitchPreferenceController.class); - final MobileNetworkPreferenceController mobileNetworkPreferenceController = - mock(MobileNetworkPreferenceController.class); - final TetherPreferenceController tetherPreferenceController = - mock(TetherPreferenceController.class); - - final SummaryLoader summaryLoader = mock(SummaryLoader.class); - final SummaryLoader.SummaryProvider provider = - new NetworkDashboardFragment.SummaryProvider(mContext, summaryLoader, - wifiPreferenceController, mobileNetworkPreferenceController, - tetherPreferenceController, () -> false); - - provider.setListening(false); - - verifyZeroInteractions(summaryLoader); - - when(wifiPreferenceController.isAvailable()).thenReturn(true); - when(mobileNetworkPreferenceController.isAvailable()).thenReturn(true); - when(tetherPreferenceController.isAvailable()).thenReturn(true); - - provider.setListening(true); - - verify(summaryLoader).setSummary(provider, "Wi\u2011Fi, mobile, and hotspot"); - } - - } diff --git a/tests/unit/src/com/android/settings/dashboard/DashboardSummaryInstrumentationTest.java b/tests/unit/src/com/android/settings/dashboard/DashboardSummaryInstrumentationTest.java deleted file mode 100644 index c21f0c0e124..00000000000 --- a/tests/unit/src/com/android/settings/dashboard/DashboardSummaryInstrumentationTest.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settings.dashboard; - -import static com.google.common.truth.Truth.assertThat; - -import android.app.Instrumentation; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ActivityInfo; -import android.provider.Settings; -import android.support.test.InstrumentationRegistry; -import android.support.test.filters.SmallTest; -import android.support.test.runner.AndroidJUnit4; -import android.support.test.uiautomator.By; -import android.support.test.uiautomator.UiDevice; -import android.support.test.uiautomator.UiObject2; -import android.support.test.uiautomator.Until; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.List; - -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentActivity; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class DashboardSummaryInstrumentationTest { - - private static final long TIMEOUT = 2000l; - - private Context mContext; - private Instrumentation mInstrumentation; - - private UiDevice mDevice; - - @Before - public void setUp() { - mInstrumentation = InstrumentationRegistry.getInstrumentation(); - mDevice = UiDevice.getInstance(mInstrumentation); - mContext = InstrumentationRegistry.getTargetContext(); - } - - @Test - public void rotate_shouldSaveCategoriesChangedState() { - final Intent intent = new Intent(Settings.ACTION_SETTINGS) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - final FragmentActivity activity = - (FragmentActivity) mInstrumentation.startActivitySync(intent); - - activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); - activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); - - final UiObject2 item = mDevice.wait(Until.findObject(By.res("android:id/title") - .text("Network & internet")), TIMEOUT); - assertThat(item).isNotNull(); - - final List fragments = activity.getSupportFragmentManager().getFragments(); - final DashboardSummary fragment = (DashboardSummary) fragments.get(0); - - assertThat(fragment.mIsOnCategoriesChangedCalled).isTrue(); - } - -}