OSDN Git Service

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