1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.homepage.contextualcards.legacysuggestion; 18 19 import android.app.PendingIntent; 20 import android.content.ComponentName; 21 import android.content.Context; 22 import android.service.settings.suggestions.Suggestion; 23 import android.util.ArrayMap; 24 import android.util.Log; 25 26 import androidx.annotation.VisibleForTesting; 27 28 import com.android.settings.R; 29 import com.android.settings.homepage.contextualcards.ContextualCard; 30 import com.android.settings.homepage.contextualcards.ContextualCardController; 31 import com.android.settings.homepage.contextualcards.ContextualCardUpdateListener; 32 import com.android.settings.overlay.FeatureFactory; 33 import com.android.settingslib.core.lifecycle.LifecycleObserver; 34 import com.android.settingslib.core.lifecycle.events.OnStart; 35 import com.android.settingslib.core.lifecycle.events.OnStop; 36 import com.android.settingslib.suggestions.SuggestionController; 37 import com.android.settingslib.suggestions.SuggestionController.ServiceConnectionListener; 38 import com.android.settingslib.utils.ThreadUtils; 39 40 import java.util.ArrayList; 41 import java.util.List; 42 import java.util.Map; 43 44 public class LegacySuggestionContextualCardController implements ContextualCardController, 45 LifecycleObserver, OnStart, OnStop, ServiceConnectionListener { 46 47 private static final String TAG = "LegacySuggestCardCtrl"; 48 49 @VisibleForTesting 50 final List<ContextualCard> mSuggestions; 51 52 @VisibleForTesting 53 SuggestionController mSuggestionController; 54 55 private ContextualCardUpdateListener mCardUpdateListener; 56 private final Context mContext; 57 58 LegacySuggestionContextualCardController(Context context)59 public LegacySuggestionContextualCardController(Context context) { 60 mContext = context; 61 mSuggestions = new ArrayList<>(); 62 if (!mContext.getResources().getBoolean(R.bool.config_use_legacy_suggestion)) { 63 Log.w(TAG, "Legacy suggestion contextual card disabled, skipping."); 64 return; 65 } 66 final ComponentName suggestionServiceComponent = 67 FeatureFactory.getFeatureFactory().getSuggestionFeatureProvider() 68 .getSuggestionServiceComponent(); 69 mSuggestionController = new SuggestionController( 70 mContext, suggestionServiceComponent, this /* listener */); 71 72 } 73 74 @Override getCardType()75 public int getCardType() { 76 return ContextualCard.CardType.LEGACY_SUGGESTION; 77 } 78 79 @Override onPrimaryClick(ContextualCard card)80 public void onPrimaryClick(ContextualCard card) { 81 try { 82 ((LegacySuggestionContextualCard) card).getPendingIntent().send(); 83 } catch (PendingIntent.CanceledException e) { 84 Log.w(TAG, "Failed to start suggestion " + card.getTitleText()); 85 } 86 } 87 88 @Override onActionClick(ContextualCard card)89 public void onActionClick(ContextualCard card) { 90 91 } 92 93 @Override onDismissed(ContextualCard card)94 public void onDismissed(ContextualCard card) { 95 mSuggestionController 96 .dismissSuggestions(((LegacySuggestionContextualCard) card).getSuggestion()); 97 mSuggestions.remove(card); 98 updateAdapter(); 99 } 100 101 @Override setCardUpdateListener(ContextualCardUpdateListener listener)102 public void setCardUpdateListener(ContextualCardUpdateListener listener) { 103 mCardUpdateListener = listener; 104 } 105 106 @Override onStart()107 public void onStart() { 108 if (mSuggestionController == null) { 109 return; 110 } 111 mSuggestionController.start(); 112 } 113 114 @Override onStop()115 public void onStop() { 116 if (mSuggestionController == null) { 117 return; 118 } 119 mSuggestionController.stop(); 120 } 121 122 @Override onServiceConnected()123 public void onServiceConnected() { 124 loadSuggestions(); 125 } 126 127 @Override onServiceDisconnected()128 public void onServiceDisconnected() { 129 130 } 131 loadSuggestions()132 private void loadSuggestions() { 133 ThreadUtils.postOnBackgroundThread(() -> { 134 if (mSuggestionController == null || mCardUpdateListener == null) { 135 return; 136 } 137 final List<Suggestion> suggestions = mSuggestionController.getSuggestions(); 138 final String suggestionCount = suggestions == null 139 ? "null" 140 : String.valueOf(suggestions.size()); 141 Log.d(TAG, "Loaded suggests: " + suggestionCount); 142 143 final List<ContextualCard> cards = new ArrayList<>(); 144 if (suggestions != null) { 145 // Convert suggestion to ContextualCard 146 for (Suggestion suggestion : suggestions) { 147 final LegacySuggestionContextualCard.Builder cardBuilder = 148 new LegacySuggestionContextualCard.Builder(); 149 if (suggestion.getIcon() != null) { 150 cardBuilder.setIconDrawable(suggestion.getIcon().loadDrawable(mContext)); 151 } 152 cardBuilder 153 .setPendingIntent(suggestion.getPendingIntent()) 154 .setSuggestion(suggestion) 155 .setName(suggestion.getId()) 156 .setTitleText(suggestion.getTitle().toString()) 157 .setSummaryText(suggestion.getSummary().toString()) 158 .setViewType(LegacySuggestionContextualCardRenderer.VIEW_TYPE); 159 160 cards.add(cardBuilder.build()); 161 } 162 } 163 164 mSuggestions.clear(); 165 mSuggestions.addAll(cards); 166 updateAdapter(); 167 }); 168 } 169 updateAdapter()170 private void updateAdapter() { 171 final Map<Integer, List<ContextualCard>> suggestionCards = new ArrayMap<>(); 172 suggestionCards.put(ContextualCard.CardType.LEGACY_SUGGESTION, mSuggestions); 173 ThreadUtils.postOnMainThread( 174 () -> mCardUpdateListener.onContextualCardUpdated(suggestionCards)); 175 } 176 } 177