• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 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.print;
18 
19 import android.app.LoaderManager.LoaderCallbacks;
20 import android.content.ActivityNotFoundException;
21 import android.content.AsyncTaskLoader;
22 import android.content.ComponentName;
23 import android.content.ContentResolver;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.Loader;
27 import android.content.pm.PackageManager;
28 import android.content.pm.ResolveInfo;
29 import android.database.ContentObserver;
30 import android.graphics.drawable.Drawable;
31 import android.net.Uri;
32 import android.os.Bundle;
33 import android.os.Handler;
34 import android.os.Message;
35 import android.os.UserHandle;
36 import android.os.UserManager;
37 import android.preference.Preference;
38 import android.preference.PreferenceCategory;
39 import android.preference.PreferenceScreen;
40 import android.print.PrintJob;
41 import android.print.PrintJobId;
42 import android.print.PrintJobInfo;
43 import android.print.PrintManager;
44 import android.print.PrintManager.PrintJobStateChangeListener;
45 import android.printservice.PrintServiceInfo;
46 import android.provider.SearchIndexableResource;
47 import android.provider.Settings;
48 import android.text.TextUtils;
49 import android.text.format.DateUtils;
50 import android.util.Log;
51 import android.view.View;
52 import android.view.View.OnClickListener;
53 import android.view.ViewGroup;
54 import android.widget.AdapterView;
55 import android.widget.AdapterView.OnItemSelectedListener;
56 import android.widget.Button;
57 import android.widget.Spinner;
58 import android.widget.TextView;
59 
60 import com.android.internal.content.PackageMonitor;
61 import com.android.internal.logging.MetricsLogger;
62 import com.android.settings.DialogCreatable;
63 import com.android.settings.R;
64 import com.android.settings.SettingsPreferenceFragment;
65 import com.android.settings.UserAdapter;
66 import com.android.settings.Utils;
67 import com.android.settings.search.BaseSearchIndexProvider;
68 import com.android.settings.search.Indexable;
69 import com.android.settings.search.SearchIndexableRaw;
70 
71 import java.text.DateFormat;
72 import java.util.ArrayList;
73 import java.util.List;
74 
75 /**
76  * Fragment with the top level print settings.
77  */
78 public class PrintSettingsFragment extends SettingsPreferenceFragment
79         implements DialogCreatable, Indexable, OnItemSelectedListener, OnClickListener {
80     public static final String TAG = "PrintSettingsFragment";
81     private static final int LOADER_ID_PRINT_JOBS_LOADER = 1;
82 
83     private static final String PRINT_JOBS_CATEGORY = "print_jobs_category";
84     private static final String PRINT_SERVICES_CATEGORY = "print_services_category";
85 
86     // Extras passed to sub-fragments.
87     static final String EXTRA_PREFERENCE_KEY = "EXTRA_PREFERENCE_KEY";
88     static final String EXTRA_CHECKED = "EXTRA_CHECKED";
89     static final String EXTRA_TITLE = "EXTRA_TITLE";
90     static final String EXTRA_ENABLE_WARNING_TITLE = "EXTRA_ENABLE_WARNING_TITLE";
91     static final String EXTRA_ENABLE_WARNING_MESSAGE = "EXTRA_ENABLE_WARNING_MESSAGE";
92     static final String EXTRA_SETTINGS_TITLE = "EXTRA_SETTINGS_TITLE";
93     static final String EXTRA_SETTINGS_COMPONENT_NAME = "EXTRA_SETTINGS_COMPONENT_NAME";
94     static final String EXTRA_ADD_PRINTERS_TITLE = "EXTRA_ADD_PRINTERS_TITLE";
95     static final String EXTRA_ADD_PRINTERS_COMPONENT_NAME = "EXTRA_ADD_PRINTERS_COMPONENT_NAME";
96     static final String EXTRA_SERVICE_COMPONENT_NAME = "EXTRA_SERVICE_COMPONENT_NAME";
97 
98     static final String EXTRA_PRINT_JOB_ID = "EXTRA_PRINT_JOB_ID";
99 
100     private static final String EXTRA_PRINT_SERVICE_COMPONENT_NAME =
101             "EXTRA_PRINT_SERVICE_COMPONENT_NAME";
102 
103     private static final int ORDER_LAST = 1000;
104 
105     private final PackageMonitor mSettingsPackageMonitor = new SettingsPackageMonitor();
106 
107     private final Handler mHandler = new Handler() {
108         @Override
109         public void dispatchMessage(Message msg) {
110             updateServicesPreferences();
111         }
112     };
113 
114     private final SettingsContentObserver mSettingsContentObserver =
115             new SettingsContentObserver(mHandler) {
116         @Override
117         public void onChange(boolean selfChange, Uri uri) {
118             updateServicesPreferences();
119         }
120     };
121 
122     private PreferenceCategory mActivePrintJobsCategory;
123     private PreferenceCategory mPrintServicesCategory;
124 
125     private PrintJobsController mPrintJobsController;
126     private UserAdapter mProfileSpinnerAdapter;
127     private Spinner mSpinner;
128     private Button mAddNewServiceButton;
129 
130     @Override
getMetricsCategory()131     protected int getMetricsCategory() {
132         return MetricsLogger.PRINT_SETTINGS;
133     }
134 
135     @Override
getHelpResource()136     protected int getHelpResource() {
137         return R.string.help_uri_printing;
138     }
139 
140     @Override
onCreate(Bundle icicle)141     public void onCreate(Bundle icicle) {
142         super.onCreate(icicle);
143         addPreferencesFromResource(R.xml.print_settings);
144 
145         mActivePrintJobsCategory = (PreferenceCategory) findPreference(
146                 PRINT_JOBS_CATEGORY);
147         mPrintServicesCategory = (PreferenceCategory) findPreference(
148                 PRINT_SERVICES_CATEGORY);
149         getPreferenceScreen().removePreference(mActivePrintJobsCategory);
150 
151         mPrintJobsController = new PrintJobsController();
152         getActivity().getLoaderManager().initLoader(LOADER_ID_PRINT_JOBS_LOADER,
153                 null, mPrintJobsController);
154     }
155 
156     @Override
onResume()157     public void onResume() {
158         super.onResume();
159         mSettingsPackageMonitor.register(getActivity(), getActivity().getMainLooper(), false);
160         mSettingsContentObserver.register(getContentResolver());
161         updateServicesPreferences();
162         setHasOptionsMenu(true);
163         startSubSettingsIfNeeded();
164     }
165 
166     @Override
onPause()167     public void onPause() {
168         mSettingsPackageMonitor.unregister();
169         mSettingsContentObserver.unregister(getContentResolver());
170         super.onPause();
171     }
172 
173     @Override
onViewCreated(View view, Bundle savedInstanceState)174     public void onViewCreated(View view, Bundle savedInstanceState) {
175         super.onViewCreated(view, savedInstanceState);
176         ViewGroup contentRoot = (ViewGroup) getListView().getParent();
177         View emptyView = getActivity().getLayoutInflater().inflate(
178                 R.layout.empty_print_state, contentRoot, false);
179         TextView textView = (TextView) emptyView.findViewById(R.id.message);
180         textView.setText(R.string.print_no_services_installed);
181 
182         final Intent addNewServiceIntent = createAddNewServiceIntentOrNull();
183         if (addNewServiceIntent != null) {
184             mAddNewServiceButton = (Button) emptyView.findViewById(R.id.add_new_service);
185             mAddNewServiceButton.setOnClickListener(this);
186             // The empty is used elsewhere too so it's hidden by default.
187             mAddNewServiceButton.setVisibility(View.VISIBLE);
188         }
189 
190         contentRoot.addView(emptyView);
191         getListView().setEmptyView(emptyView);
192 
193         final UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
194         mProfileSpinnerAdapter = Utils.createUserSpinnerAdapter(um, getActivity());
195         if (mProfileSpinnerAdapter != null) {
196             mSpinner = (Spinner) setPinnedHeaderView(R.layout.spinner_view);
197             mSpinner.setAdapter(mProfileSpinnerAdapter);
198             mSpinner.setOnItemSelectedListener(this);
199         }
200     }
201 
updateServicesPreferences()202     private void updateServicesPreferences() {
203         if (getPreferenceScreen().findPreference(PRINT_SERVICES_CATEGORY) == null) {
204             getPreferenceScreen().addPreference(mPrintServicesCategory);
205         } else {
206             // Since services category is auto generated we have to do a pass
207             // to generate it since services can come and go.
208             mPrintServicesCategory.removeAll();
209         }
210 
211         List<ComponentName> enabledServices = PrintSettingsUtils
212                 .readEnabledPrintServices(getActivity());
213 
214         final PackageManager pm = getActivity().getPackageManager();
215 
216         List<ResolveInfo> installedServices = pm
217                 .queryIntentServices(
218                         new Intent(android.printservice.PrintService.SERVICE_INTERFACE),
219                         PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
220 
221         final int installedServiceCount = installedServices.size();
222         for (int i = 0; i < installedServiceCount; i++) {
223             ResolveInfo installedService = installedServices.get(i);
224 
225             PreferenceScreen preference = getPreferenceManager().createPreferenceScreen(
226                     getActivity());
227 
228             String title = installedService.loadLabel(getPackageManager()).toString();
229             preference.setTitle(title);
230 
231             ComponentName componentName = new ComponentName(
232                     installedService.serviceInfo.packageName,
233                     installedService.serviceInfo.name);
234             preference.setKey(componentName.flattenToString());
235 
236             preference.setOrder(i);
237             preference.setFragment(PrintServiceSettingsFragment.class.getName());
238             preference.setPersistent(false);
239 
240             final boolean serviceEnabled = enabledServices.contains(componentName);
241             if (serviceEnabled) {
242                 preference.setSummary(getString(R.string.print_feature_state_on));
243             } else {
244                 preference.setSummary(getString(R.string.print_feature_state_off));
245             }
246 
247             final Drawable drawable = installedService.loadIcon(pm);
248             if (drawable != null) {
249                 preference.setIcon(drawable);
250             }
251 
252             Bundle extras = preference.getExtras();
253             extras.putString(EXTRA_PREFERENCE_KEY, preference.getKey());
254             extras.putBoolean(EXTRA_CHECKED, serviceEnabled);
255             extras.putString(EXTRA_TITLE, title);
256 
257             PrintServiceInfo printServiceInfo = PrintServiceInfo.create(
258                     installedService, getActivity());
259 
260             CharSequence applicationLabel = installedService.loadLabel(getPackageManager());
261 
262             extras.putString(EXTRA_ENABLE_WARNING_TITLE, getString(
263                     R.string.print_service_security_warning_title, applicationLabel));
264             extras.putString(EXTRA_ENABLE_WARNING_MESSAGE, getString(
265                     R.string.print_service_security_warning_summary, applicationLabel));
266 
267             String settingsClassName = printServiceInfo.getSettingsActivityName();
268             if (!TextUtils.isEmpty(settingsClassName)) {
269                 extras.putString(EXTRA_SETTINGS_TITLE,
270                         getString(R.string.print_menu_item_settings));
271                 extras.putString(EXTRA_SETTINGS_COMPONENT_NAME,
272                         new ComponentName(installedService.serviceInfo.packageName,
273                                 settingsClassName).flattenToString());
274             }
275 
276             String addPrinterClassName = printServiceInfo.getAddPrintersActivityName();
277             if (!TextUtils.isEmpty(addPrinterClassName)) {
278                 extras.putString(EXTRA_ADD_PRINTERS_TITLE,
279                         getString(R.string.print_menu_item_add_printers));
280                 extras.putString(EXTRA_ADD_PRINTERS_COMPONENT_NAME,
281                         new ComponentName(installedService.serviceInfo.packageName,
282                                 addPrinterClassName).flattenToString());
283             }
284 
285             extras.putString(EXTRA_SERVICE_COMPONENT_NAME, componentName.flattenToString());
286 
287             mPrintServicesCategory.addPreference(preference);
288         }
289 
290         if (mPrintServicesCategory.getPreferenceCount() == 0) {
291             getPreferenceScreen().removePreference(mPrintServicesCategory);
292         } else {
293             final Preference addNewServicePreference = newAddServicePreferenceOrNull();
294             if (addNewServicePreference != null) {
295                 mPrintServicesCategory.addPreference(addNewServicePreference);
296             }
297         }
298     }
299 
newAddServicePreferenceOrNull()300     private Preference newAddServicePreferenceOrNull() {
301         final Intent addNewServiceIntent = createAddNewServiceIntentOrNull();
302         if (addNewServiceIntent == null) {
303             return null;
304         }
305         Preference preference = new Preference(getContext());
306         preference.setTitle(R.string.print_menu_item_add_service);
307         preference.setIcon(R.drawable.ic_menu_add);
308         preference.setOrder(ORDER_LAST);
309         preference.setIntent(addNewServiceIntent);
310         preference.setPersistent(false);
311         return preference;
312     }
313 
createAddNewServiceIntentOrNull()314     private Intent createAddNewServiceIntentOrNull() {
315         final String searchUri = Settings.Secure.getString(getContentResolver(),
316                 Settings.Secure.PRINT_SERVICE_SEARCH_URI);
317         if (TextUtils.isEmpty(searchUri)) {
318             return null;
319         }
320         return new Intent(Intent.ACTION_VIEW, Uri.parse(searchUri));
321     }
322 
startSubSettingsIfNeeded()323     private void startSubSettingsIfNeeded() {
324         if (getArguments() == null) {
325             return;
326         }
327         String componentName = getArguments().getString(EXTRA_PRINT_SERVICE_COMPONENT_NAME);
328         if (componentName != null) {
329             getArguments().remove(EXTRA_PRINT_SERVICE_COMPONENT_NAME);
330             Preference prereference = findPreference(componentName);
331             if (prereference != null) {
332                 prereference.performClick(getPreferenceScreen());
333             }
334         }
335     }
336 
337     @Override
onItemSelected(AdapterView<?> parent, View view, int position, long id)338     public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
339         UserHandle selectedUser = mProfileSpinnerAdapter.getUserHandle(position);
340         if (selectedUser.getIdentifier() != UserHandle.myUserId()) {
341             Intent intent = new Intent(Settings.ACTION_PRINT_SETTINGS);
342             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
343             intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
344             getActivity().startActivityAsUser(intent, selectedUser);
345             // Go back to default selection, which is the first one
346             mSpinner.setSelection(0);
347         }
348     }
349 
350     @Override
onNothingSelected(AdapterView<?> parent)351     public void onNothingSelected(AdapterView<?> parent) {
352         // Nothing to do
353     }
354 
355     @Override
onClick(View v)356     public void onClick(View v) {
357         if (mAddNewServiceButton == v) {
358             final Intent addNewServiceIntent = createAddNewServiceIntentOrNull();
359             if (addNewServiceIntent != null) { // check again just in case.
360                 try {
361                     startActivity(addNewServiceIntent);
362                 } catch (ActivityNotFoundException e) {
363                     Log.w(TAG, "Unable to start activity", e);
364                 }
365             }
366         }
367     }
368 
369     private class SettingsPackageMonitor extends PackageMonitor {
370         @Override
onPackageAdded(String packageName, int uid)371         public void onPackageAdded(String packageName, int uid) {
372             mHandler.obtainMessage().sendToTarget();
373         }
374 
375         @Override
onPackageAppeared(String packageName, int reason)376         public void onPackageAppeared(String packageName, int reason) {
377             mHandler.obtainMessage().sendToTarget();
378         }
379 
380         @Override
onPackageDisappeared(String packageName, int reason)381         public void onPackageDisappeared(String packageName, int reason) {
382             mHandler.obtainMessage().sendToTarget();
383         }
384 
385         @Override
onPackageRemoved(String packageName, int uid)386         public void onPackageRemoved(String packageName, int uid) {
387             mHandler.obtainMessage().sendToTarget();
388         }
389     }
390 
391     private static abstract class SettingsContentObserver extends ContentObserver {
392 
SettingsContentObserver(Handler handler)393         public SettingsContentObserver(Handler handler) {
394             super(handler);
395         }
396 
register(ContentResolver contentResolver)397         public void register(ContentResolver contentResolver) {
398             contentResolver.registerContentObserver(Settings.Secure.getUriFor(
399                     Settings.Secure.ENABLED_PRINT_SERVICES), false, this);
400         }
401 
unregister(ContentResolver contentResolver)402         public void unregister(ContentResolver contentResolver) {
403             contentResolver.unregisterContentObserver(this);
404         }
405 
406         @Override
onChange(boolean selfChange, Uri uri)407         public abstract void onChange(boolean selfChange, Uri uri);
408     }
409 
410     private final class PrintJobsController implements LoaderCallbacks<List<PrintJobInfo>> {
411 
412         @Override
onCreateLoader(int id, Bundle args)413         public Loader<List<PrintJobInfo>> onCreateLoader(int id, Bundle args) {
414             if (id == LOADER_ID_PRINT_JOBS_LOADER) {
415                 return new PrintJobsLoader(getActivity());
416             }
417             return null;
418         }
419 
420         @Override
onLoadFinished(Loader<List<PrintJobInfo>> loader, List<PrintJobInfo> printJobs)421         public void onLoadFinished(Loader<List<PrintJobInfo>> loader,
422                 List<PrintJobInfo> printJobs) {
423             if (printJobs == null || printJobs.isEmpty()) {
424                 getPreferenceScreen().removePreference(mActivePrintJobsCategory);
425             } else {
426                 if (getPreferenceScreen().findPreference(PRINT_JOBS_CATEGORY) == null) {
427                     getPreferenceScreen().addPreference(mActivePrintJobsCategory);
428                 }
429 
430                 mActivePrintJobsCategory.removeAll();
431 
432                 final int printJobCount = printJobs.size();
433                 for (int i = 0; i < printJobCount; i++) {
434                     PrintJobInfo printJob = printJobs.get(i);
435 
436                     PreferenceScreen preference = getPreferenceManager()
437                             .createPreferenceScreen(getActivity());
438 
439                     preference.setPersistent(false);
440                     preference.setFragment(PrintJobSettingsFragment.class.getName());
441                     preference.setKey(printJob.getId().flattenToString());
442 
443                     switch (printJob.getState()) {
444                         case PrintJobInfo.STATE_QUEUED:
445                         case PrintJobInfo.STATE_STARTED: {
446                             if (!printJob.isCancelling()) {
447                                 preference.setTitle(getString(
448                                         R.string.print_printing_state_title_template,
449                                         printJob.getLabel()));
450                             } else {
451                                 preference.setTitle(getString(
452                                         R.string.print_cancelling_state_title_template,
453                                         printJob.getLabel()));
454                             }
455                         } break;
456 
457                         case PrintJobInfo.STATE_FAILED: {
458                             preference.setTitle(getString(
459                                     R.string.print_failed_state_title_template,
460                                     printJob.getLabel()));
461                         } break;
462 
463                         case PrintJobInfo.STATE_BLOCKED: {
464                             if (!printJob.isCancelling()) {
465                                 preference.setTitle(getString(
466                                         R.string.print_blocked_state_title_template,
467                                         printJob.getLabel()));
468                             } else {
469                                 preference.setTitle(getString(
470                                         R.string.print_cancelling_state_title_template,
471                                         printJob.getLabel()));
472                             }
473                         } break;
474                     }
475 
476                     preference.setSummary(getString(R.string.print_job_summary,
477                             printJob.getPrinterName(), DateUtils.formatSameDayTime(
478                                     printJob.getCreationTime(), printJob.getCreationTime(),
479                                     DateFormat.SHORT, DateFormat.SHORT)));
480 
481                     switch (printJob.getState()) {
482                         case PrintJobInfo.STATE_QUEUED:
483                         case PrintJobInfo.STATE_STARTED: {
484                             preference.setIcon(R.drawable.ic_print);
485                         } break;
486 
487                         case PrintJobInfo.STATE_FAILED:
488                         case PrintJobInfo.STATE_BLOCKED: {
489                             preference.setIcon(R.drawable.ic_print_error);
490                         } break;
491                     }
492 
493                     Bundle extras = preference.getExtras();
494                     extras.putString(EXTRA_PRINT_JOB_ID, printJob.getId().flattenToString());
495 
496                     mActivePrintJobsCategory.addPreference(preference);
497                 }
498             }
499         }
500 
501         @Override
onLoaderReset(Loader<List<PrintJobInfo>> loader)502         public void onLoaderReset(Loader<List<PrintJobInfo>> loader) {
503             getPreferenceScreen().removePreference(mActivePrintJobsCategory);
504         }
505     }
506 
507     private static final class PrintJobsLoader extends AsyncTaskLoader<List<PrintJobInfo>> {
508 
509         private static final String LOG_TAG = "PrintJobsLoader";
510 
511         private static final boolean DEBUG = false;
512 
513         private List<PrintJobInfo> mPrintJobs = new ArrayList<PrintJobInfo>();
514 
515         private final PrintManager mPrintManager;
516 
517         private PrintJobStateChangeListener mPrintJobStateChangeListener;
518 
PrintJobsLoader(Context context)519         public PrintJobsLoader(Context context) {
520             super(context);
521             mPrintManager = ((PrintManager) context.getSystemService(
522                     Context.PRINT_SERVICE)).getGlobalPrintManagerForUser(
523                     context.getUserId());
524         }
525 
526         @Override
deliverResult(List<PrintJobInfo> printJobs)527         public void deliverResult(List<PrintJobInfo> printJobs) {
528             if (isStarted()) {
529                 super.deliverResult(printJobs);
530             }
531         }
532 
533         @Override
onStartLoading()534         protected void onStartLoading() {
535             if (DEBUG) {
536                 Log.i(LOG_TAG, "onStartLoading()");
537             }
538             // If we already have a result, deliver it immediately.
539             if (!mPrintJobs.isEmpty()) {
540                 deliverResult(new ArrayList<PrintJobInfo>(mPrintJobs));
541             }
542             // Start watching for changes.
543             if (mPrintJobStateChangeListener == null) {
544                 mPrintJobStateChangeListener = new PrintJobStateChangeListener() {
545                     @Override
546                     public void onPrintJobStateChanged(PrintJobId printJobId) {
547                         onForceLoad();
548                     }
549                 };
550                 mPrintManager.addPrintJobStateChangeListener(
551                         mPrintJobStateChangeListener);
552             }
553             // If the data changed or we have no data - load it now.
554             if (mPrintJobs.isEmpty()) {
555                 onForceLoad();
556             }
557         }
558 
559         @Override
onStopLoading()560         protected void onStopLoading() {
561             if (DEBUG) {
562                 Log.i(LOG_TAG, "onStopLoading()");
563             }
564             // Cancel the load in progress if possible.
565             onCancelLoad();
566         }
567 
568         @Override
onReset()569         protected void onReset() {
570             if (DEBUG) {
571                 Log.i(LOG_TAG, "onReset()");
572             }
573             // Stop loading.
574             onStopLoading();
575             // Clear the cached result.
576             mPrintJobs.clear();
577             // Stop watching for changes.
578             if (mPrintJobStateChangeListener != null) {
579                 mPrintManager.removePrintJobStateChangeListener(
580                         mPrintJobStateChangeListener);
581                 mPrintJobStateChangeListener = null;
582             }
583         }
584 
585         @Override
loadInBackground()586         public List<PrintJobInfo> loadInBackground() {
587             List<PrintJobInfo> printJobInfos = null;
588             List<PrintJob> printJobs = mPrintManager.getPrintJobs();
589             final int printJobCount = printJobs.size();
590             for (int i = 0; i < printJobCount; i++) {
591                 PrintJobInfo printJob = printJobs.get(i).getInfo();
592                 if (shouldShowToUser(printJob)) {
593                     if (printJobInfos == null) {
594                         printJobInfos = new ArrayList<PrintJobInfo>();
595                     }
596                     printJobInfos.add(printJob);
597                 }
598             }
599             return printJobInfos;
600         }
601 
shouldShowToUser(PrintJobInfo printJob)602         private static boolean shouldShowToUser(PrintJobInfo printJob) {
603             switch (printJob.getState()) {
604                 case PrintJobInfo.STATE_QUEUED:
605                 case PrintJobInfo.STATE_STARTED:
606                 case PrintJobInfo.STATE_BLOCKED:
607                 case PrintJobInfo.STATE_FAILED: {
608                     return true;
609                 }
610             }
611             return false;
612         }
613     }
614 
615     public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
616             new BaseSearchIndexProvider() {
617         @Override
618         public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
619             List<SearchIndexableRaw> indexables = new ArrayList<SearchIndexableRaw>();
620 
621             PackageManager packageManager = context.getPackageManager();
622             PrintManager printManager = (PrintManager) context.getSystemService(
623                     Context.PRINT_SERVICE);
624 
625             String screenTitle = context.getResources().getString(R.string.print_settings);
626             SearchIndexableRaw data = new SearchIndexableRaw(context);
627             data.title = screenTitle;
628             data.screenTitle = screenTitle;
629             indexables.add(data);
630 
631             // Indexing all services, regardless if enabled.
632             List<PrintServiceInfo> services = printManager.getInstalledPrintServices();
633             final int serviceCount = services.size();
634             for (int i = 0; i < serviceCount; i++) {
635                 PrintServiceInfo service = services.get(i);
636 
637                 ComponentName componentName = new ComponentName(
638                         service.getResolveInfo().serviceInfo.packageName,
639                         service.getResolveInfo().serviceInfo.name);
640 
641                 data = new SearchIndexableRaw(context);
642                 data.key = componentName.flattenToString();
643                 data.title = service.getResolveInfo().loadLabel(packageManager).toString();
644                 data.summaryOn = context.getString(R.string.print_feature_state_on);
645                 data.summaryOff = context.getString(R.string.print_feature_state_off);
646                 data.screenTitle = screenTitle;
647                 indexables.add(data);
648             }
649 
650             return indexables;
651         }
652 
653         @Override
654         public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
655                 boolean enabled) {
656             List<SearchIndexableResource> indexables = new ArrayList<SearchIndexableResource>();
657             SearchIndexableResource indexable = new SearchIndexableResource(context);
658             indexable.xmlResId = R.xml.print_settings;
659             indexables.add(indexable);
660             return indexables;
661         }
662     };
663 }
664