• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package com.android.car.settings.suggestions;
17 
18 import android.annotation.NonNull;
19 import android.annotation.Nullable;
20 import android.app.PendingIntent;
21 import android.content.ComponentName;
22 import android.content.Context;
23 import android.graphics.drawable.Drawable;
24 import android.os.Bundle;
25 import android.service.settings.suggestions.Suggestion;
26 import android.support.annotation.StringRes;
27 import android.support.v4.app.LoaderManager;
28 import android.support.v4.content.Loader;
29 
30 import com.android.car.list.TypedPagedListAdapter;
31 import com.android.car.settings.R;
32 import com.android.car.settings.common.Logger;
33 import com.android.settingslib.suggestions.SuggestionController;
34 import com.android.settingslib.suggestions.SuggestionControllerMixin;
35 import com.android.settingslib.suggestions.SuggestionLoader;
36 import com.android.settingslib.utils.IconCache;
37 
38 import java.util.ArrayList;
39 import java.util.List;
40 
41 
42 /**
43  * Retrieves suggestions and prepares them for rendering.
44  * Modeled after {@link SuggestionControllerMixin}, differs by implementing support library version
45  * of LoaderManager and Loader. Does not implement use of LifeCycle.
46  */
47 public class SettingsSuggestionsController implements
48         SuggestionController.ServiceConnectionListener,
49         LoaderManager.LoaderCallbacks<List<Suggestion>> {
50     private static final Logger LOG = new Logger(SettingsSuggestionsController.class);
51     private static final ComponentName mComponentName = new ComponentName(
52             "com.android.settings.intelligence",
53             "com.android.settings.intelligence.suggestions.SuggestionService");
54     // These values are hard coded until we receive the OK to plumb them through
55     // SettingsIntelligence. This is ok as right now only SUW uses this framework.
56     @StringRes
57     private static final int PRIMARY_ACTION_ID = R.string.suggestion_primary_button;
58     @StringRes
59     private static final int SECONDARY_ACTION_ID = R.string.suggestion_secondary_button;
60 
61     private final Context mContext;
62     private final LoaderManager mLoaderManager;
63     private final Listener mListener;
64     private final SuggestionController mSuggestionController;
65     private final IconCache mIconCache;
66 
SettingsSuggestionsController( Context context, LoaderManager loaderManager, @NonNull Listener listener)67     public SettingsSuggestionsController(
68             Context context,
69             LoaderManager loaderManager,
70             @NonNull Listener listener) {
71         mContext = context;
72         mLoaderManager = loaderManager;
73         mListener = listener;
74         mIconCache = new IconCache(context);
75         mSuggestionController = new SuggestionController(
76                 mContext,
77                 mComponentName,
78                 /* listener= */ this);
79     }
80 
81     @Override
onServiceConnected()82     public void onServiceConnected() {
83         LOG.v("onServiceConnected");
84         mLoaderManager.restartLoader(
85                 SettingsSuggestionsLoader.LOADER_ID_SUGGESTIONS,
86                 /* args= */ null,
87                 /* callback= */ this);
88     }
89 
90     @Override
onServiceDisconnected()91     public void onServiceDisconnected() {
92         LOG.v("onServiceDisconnected");
93         cleanupLoader();
94     }
95 
96     @NonNull
97     @Override
onCreateLoader(int id, @Nullable Bundle args)98     public Loader<List<Suggestion>> onCreateLoader(int id, @Nullable Bundle args) {
99         LOG.v("onCreateLoader: " + id);
100         if (id == SettingsSuggestionsLoader.LOADER_ID_SUGGESTIONS) {
101             return new SettingsSuggestionsLoader(mContext, mSuggestionController);
102         }
103         throw new IllegalArgumentException("This loader id is not supported " + id);
104     }
105 
106     @Override
onLoadFinished( @onNull Loader<List<Suggestion>> loader, List<Suggestion> suggestionList)107     public void onLoadFinished(
108             @NonNull Loader<List<Suggestion>> loader,
109             List<Suggestion> suggestionList) {
110         LOG.v("onLoadFinished");
111         if (suggestionList == null) {
112             return;
113         }
114         ArrayList<TypedPagedListAdapter.LineItem> items = new ArrayList<>();
115         for (final Suggestion suggestion : suggestionList) {
116             LOG.v("Suggestion ID: " + suggestion.getId());
117             Drawable itemIcon = mIconCache.getIcon(suggestion.getIcon());
118             SuggestionLineItem suggestionLineItem =
119                     new SuggestionLineItem(
120                             suggestion.getTitle(),
121                             suggestion.getSummary(),
122                             itemIcon,
123                             mContext.getString(PRIMARY_ACTION_ID),
124                             mContext.getString(SECONDARY_ACTION_ID),
125                             v -> {
126                                 try {
127                                     suggestion.getPendingIntent().send();
128                                     launchSuggestion(suggestion);
129                                 } catch (PendingIntent.CanceledException e) {
130                                     LOG.w("Failed to start suggestion " + suggestion.getTitle());
131                                 }
132                             },
133                             adapterPosition -> {
134                                 dismissSuggestion(suggestion);
135                                 mListener.onSuggestionDismissed(adapterPosition);
136 
137                             });
138             items.add(suggestionLineItem);
139         }
140         mListener.onSuggestionsLoaded(items);
141     }
142 
143     @Override
onLoaderReset(@onNull Loader<List<Suggestion>> loader)144     public void onLoaderReset(@NonNull Loader<List<Suggestion>> loader) {
145         LOG.v("onLoaderReset");
146     }
147 
148     /**
149      * Start the suggestions controller.
150      */
start()151     public void start() {
152         LOG.v("Start");
153         mSuggestionController.start();
154     }
155 
156     /**
157      * Stop the suggestions controller.
158      */
stop()159     public void stop() {
160         LOG.v("Stop");
161         mSuggestionController.stop();
162         cleanupLoader();
163 
164     }
165 
cleanupLoader()166     private void cleanupLoader() {
167         LOG.v("cleanupLoader");
168         mLoaderManager.destroyLoader(SuggestionLoader.LOADER_ID_SUGGESTIONS);
169     }
170 
dismissSuggestion(Suggestion suggestion)171     private void dismissSuggestion(Suggestion suggestion) {
172         LOG.v("dismissSuggestion");
173         mSuggestionController.dismissSuggestions(suggestion);
174     }
175 
launchSuggestion(Suggestion suggestion)176     private void launchSuggestion(Suggestion suggestion) {
177         LOG.v("launchSuggestion");
178         mSuggestionController.launchSuggestion(suggestion);
179     }
180 
181     /**
182      * Listener interface to notify of data state changes and actions.
183      */
184     public interface Listener {
185         /**
186          * Invoked when deferred setup items have been loaded.
187          *
188          * @param suggestions List of deferred setup suggestions.
189          */
onSuggestionsLoaded(@onNull ArrayList<TypedPagedListAdapter.LineItem> suggestions)190         void onSuggestionsLoaded(@NonNull ArrayList<TypedPagedListAdapter.LineItem> suggestions);
191 
192         /***
193          * Invoked when a suggestion is dismissed.
194          *
195          * @param adapterPosition the position of the suggestion item in it's adapter.
196          */
onSuggestionDismissed(int adapterPosition)197         void onSuggestionDismissed(int adapterPosition);
198     }
199 }
200