Home | History | Annotate | Download | only in print
      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.Context;
     24 import android.content.Intent;
     25 import android.content.Loader;
     26 import android.content.pm.PackageManager;
     27 import android.graphics.drawable.Drawable;
     28 import android.net.Uri;
     29 import android.os.Bundle;
     30 import android.print.PrintJob;
     31 import android.print.PrintJobId;
     32 import android.print.PrintJobInfo;
     33 import android.print.PrintManager;
     34 import android.print.PrintManager.PrintJobStateChangeListener;
     35 import android.print.PrintServicesLoader;
     36 import android.printservice.PrintServiceInfo;
     37 import android.provider.SearchIndexableResource;
     38 import android.provider.Settings;
     39 import android.support.annotation.VisibleForTesting;
     40 import android.support.v7.preference.Preference;
     41 import android.support.v7.preference.PreferenceCategory;
     42 import android.text.TextUtils;
     43 import android.text.format.DateUtils;
     44 import android.util.Log;
     45 import android.view.LayoutInflater;
     46 import android.view.View;
     47 import android.view.View.OnClickListener;
     48 import android.view.ViewGroup;
     49 import android.widget.Button;
     50 import android.widget.TextView;
     51 
     52 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
     53 import com.android.settings.R;
     54 import com.android.settings.dashboard.SummaryLoader;
     55 import com.android.settings.search.BaseSearchIndexProvider;
     56 import com.android.settings.search.Indexable;
     57 import com.android.settings.search.SearchIndexableRaw;
     58 import com.android.settings.utils.ProfileSettingsPreferenceFragment;
     59 
     60 import java.text.DateFormat;
     61 import java.util.ArrayList;
     62 import java.util.List;
     63 
     64 /**
     65  * Fragment with the top level print settings.
     66  */
     67 public class PrintSettingsFragment extends ProfileSettingsPreferenceFragment
     68         implements Indexable, OnClickListener {
     69     public static final String TAG = "PrintSettingsFragment";
     70     private static final int LOADER_ID_PRINT_JOBS_LOADER = 1;
     71     private static final int LOADER_ID_PRINT_SERVICES = 2;
     72 
     73     private static final String PRINT_JOBS_CATEGORY = "print_jobs_category";
     74     private static final String PRINT_SERVICES_CATEGORY = "print_services_category";
     75 
     76     static final String EXTRA_CHECKED = "EXTRA_CHECKED";
     77     static final String EXTRA_TITLE = "EXTRA_TITLE";
     78     static final String EXTRA_SERVICE_COMPONENT_NAME = "EXTRA_SERVICE_COMPONENT_NAME";
     79 
     80     static final String EXTRA_PRINT_JOB_ID = "EXTRA_PRINT_JOB_ID";
     81 
     82     private static final String EXTRA_PRINT_SERVICE_COMPONENT_NAME =
     83             "EXTRA_PRINT_SERVICE_COMPONENT_NAME";
     84 
     85     private static final int ORDER_LAST = Preference.DEFAULT_ORDER - 1;
     86 
     87     private PreferenceCategory mActivePrintJobsCategory;
     88     private PreferenceCategory mPrintServicesCategory;
     89 
     90     private PrintJobsController mPrintJobsController;
     91     private PrintServicesController mPrintServicesController;
     92 
     93     private Button mAddNewServiceButton;
     94 
     95     @Override
     96     public int getMetricsCategory() {
     97         return MetricsEvent.PRINT_SETTINGS;
     98     }
     99 
    100     @Override
    101     protected int getHelpResource() {
    102         return R.string.help_uri_printing;
    103     }
    104 
    105     @Override
    106     public View onCreateView(LayoutInflater inflater, ViewGroup container,
    107             Bundle savedInstanceState) {
    108         View root = super.onCreateView(inflater, container, savedInstanceState);
    109         addPreferencesFromResource(R.xml.print_settings);
    110 
    111         mActivePrintJobsCategory = (PreferenceCategory) findPreference(
    112                 PRINT_JOBS_CATEGORY);
    113         mPrintServicesCategory = (PreferenceCategory) findPreference(
    114                 PRINT_SERVICES_CATEGORY);
    115         getPreferenceScreen().removePreference(mActivePrintJobsCategory);
    116 
    117         mPrintJobsController = new PrintJobsController();
    118         getLoaderManager().initLoader(LOADER_ID_PRINT_JOBS_LOADER, null, mPrintJobsController);
    119 
    120         mPrintServicesController = new PrintServicesController();
    121         getLoaderManager().initLoader(LOADER_ID_PRINT_SERVICES, null, mPrintServicesController);
    122 
    123         return root;
    124     }
    125 
    126     @Override
    127     public void onStart() {
    128         super.onStart();
    129         setHasOptionsMenu(true);
    130         startSubSettingsIfNeeded();
    131     }
    132 
    133     @Override
    134     public void onStop() {
    135         super.onStop();
    136     }
    137 
    138     @Override
    139     public void onViewCreated(View view, Bundle savedInstanceState) {
    140         super.onViewCreated(view, savedInstanceState);
    141         ViewGroup contentRoot = (ViewGroup) getListView().getParent();
    142         View emptyView = getActivity().getLayoutInflater().inflate(
    143                 R.layout.empty_print_state, contentRoot, false);
    144         TextView textView = (TextView) emptyView.findViewById(R.id.message);
    145         textView.setText(R.string.print_no_services_installed);
    146 
    147         final Intent addNewServiceIntent = createAddNewServiceIntentOrNull();
    148         if (addNewServiceIntent != null) {
    149             mAddNewServiceButton = (Button) emptyView.findViewById(R.id.add_new_service);
    150             mAddNewServiceButton.setOnClickListener(this);
    151             // The empty is used elsewhere too so it's hidden by default.
    152             mAddNewServiceButton.setVisibility(View.VISIBLE);
    153         }
    154 
    155         contentRoot.addView(emptyView);
    156         setEmptyView(emptyView);
    157     }
    158 
    159     @Override
    160     protected String getIntentActionString() {
    161         return Settings.ACTION_PRINT_SETTINGS;
    162     }
    163 
    164     /**
    165      * Adds preferences for all print services to the {@value PRINT_SERVICES_CATEGORY} cathegory.
    166      */
    167     private final class PrintServicesController implements LoaderCallbacks<List<PrintServiceInfo>> {
    168         @Override
    169         public Loader<List<PrintServiceInfo>> onCreateLoader(int id, Bundle args) {
    170             PrintManager printManager =
    171                     (PrintManager) getContext().getSystemService(Context.PRINT_SERVICE);
    172             if (printManager != null) {
    173                 return new PrintServicesLoader(printManager, getContext(),
    174                         PrintManager.ALL_SERVICES);
    175             } else {
    176                 return null;
    177             }
    178         }
    179 
    180         @Override
    181         public void onLoadFinished(Loader<List<PrintServiceInfo>> loader,
    182                 List<PrintServiceInfo> services) {
    183             if (services.isEmpty()) {
    184                 getPreferenceScreen().removePreference(mPrintServicesCategory);
    185                 return;
    186             } else if (getPreferenceScreen().findPreference(PRINT_SERVICES_CATEGORY) == null) {
    187                 getPreferenceScreen().addPreference(mPrintServicesCategory);
    188             }
    189 
    190             mPrintServicesCategory.removeAll();
    191             PackageManager pm = getActivity().getPackageManager();
    192             final Context context = getPrefContext();
    193             if (context == null) {
    194                 Log.w(TAG, "No preference context, skip adding print services");
    195                 return;
    196             }
    197 
    198             for (PrintServiceInfo service : services) {
    199                 Preference preference = new Preference(context);
    200 
    201                 String title = service.getResolveInfo().loadLabel(pm).toString();
    202                 preference.setTitle(title);
    203 
    204                 ComponentName componentName = service.getComponentName();
    205                 preference.setKey(componentName.flattenToString());
    206 
    207                 preference.setFragment(PrintServiceSettingsFragment.class.getName());
    208                 preference.setPersistent(false);
    209 
    210                 if (service.isEnabled()) {
    211                     preference.setSummary(getString(R.string.print_feature_state_on));
    212                 } else {
    213                     preference.setSummary(getString(R.string.print_feature_state_off));
    214                 }
    215 
    216                 Drawable drawable = service.getResolveInfo().loadIcon(pm);
    217                 if (drawable != null) {
    218                     preference.setIcon(drawable);
    219                 }
    220 
    221                 Bundle extras = preference.getExtras();
    222                 extras.putBoolean(EXTRA_CHECKED, service.isEnabled());
    223                 extras.putString(EXTRA_TITLE, title);
    224                 extras.putString(EXTRA_SERVICE_COMPONENT_NAME, componentName.flattenToString());
    225 
    226                 mPrintServicesCategory.addPreference(preference);
    227             }
    228 
    229             Preference addNewServicePreference = newAddServicePreferenceOrNull();
    230             if (addNewServicePreference != null) {
    231                 mPrintServicesCategory.addPreference(addNewServicePreference);
    232             }
    233         }
    234 
    235         @Override
    236         public void onLoaderReset(Loader<List<PrintServiceInfo>> loader) {
    237             getPreferenceScreen().removePreference(mPrintServicesCategory);
    238         }
    239     }
    240 
    241     private Preference newAddServicePreferenceOrNull() {
    242         final Intent addNewServiceIntent = createAddNewServiceIntentOrNull();
    243         if (addNewServiceIntent == null) {
    244             return null;
    245         }
    246         Preference preference = new Preference(getPrefContext());
    247         preference.setTitle(R.string.print_menu_item_add_service);
    248         preference.setIcon(R.drawable.ic_menu_add);
    249         preference.setOrder(ORDER_LAST);
    250         preference.setIntent(addNewServiceIntent);
    251         preference.setPersistent(false);
    252         return preference;
    253     }
    254 
    255     private Intent createAddNewServiceIntentOrNull() {
    256         final String searchUri = Settings.Secure.getString(getContentResolver(),
    257                 Settings.Secure.PRINT_SERVICE_SEARCH_URI);
    258         if (TextUtils.isEmpty(searchUri)) {
    259             return null;
    260         }
    261         return new Intent(Intent.ACTION_VIEW, Uri.parse(searchUri));
    262     }
    263 
    264     private void startSubSettingsIfNeeded() {
    265         if (getArguments() == null) {
    266             return;
    267         }
    268         String componentName = getArguments().getString(EXTRA_PRINT_SERVICE_COMPONENT_NAME);
    269         if (componentName != null) {
    270             getArguments().remove(EXTRA_PRINT_SERVICE_COMPONENT_NAME);
    271             Preference prereference = findPreference(componentName);
    272             if (prereference != null) {
    273                 prereference.performClick();
    274             }
    275         }
    276     }
    277 
    278     @Override
    279     public void onClick(View v) {
    280         if (mAddNewServiceButton == v) {
    281             final Intent addNewServiceIntent = createAddNewServiceIntentOrNull();
    282             if (addNewServiceIntent != null) { // check again just in case.
    283                 try {
    284                     startActivity(addNewServiceIntent);
    285                 } catch (ActivityNotFoundException e) {
    286                     Log.w(TAG, "Unable to start activity", e);
    287                 }
    288             }
    289         }
    290     }
    291 
    292     private final class PrintJobsController implements LoaderCallbacks<List<PrintJobInfo>> {
    293 
    294         @Override
    295         public Loader<List<PrintJobInfo>> onCreateLoader(int id, Bundle args) {
    296             if (id == LOADER_ID_PRINT_JOBS_LOADER) {
    297                 return new PrintJobsLoader(getContext());
    298             }
    299             return null;
    300         }
    301 
    302         @Override
    303         public void onLoadFinished(Loader<List<PrintJobInfo>> loader,
    304                 List<PrintJobInfo> printJobs) {
    305             if (printJobs == null || printJobs.isEmpty()) {
    306                 getPreferenceScreen().removePreference(mActivePrintJobsCategory);
    307             } else {
    308                 if (getPreferenceScreen().findPreference(PRINT_JOBS_CATEGORY) == null) {
    309                     getPreferenceScreen().addPreference(mActivePrintJobsCategory);
    310                 }
    311 
    312                 mActivePrintJobsCategory.removeAll();
    313                 final Context context = getPrefContext();
    314                 if (context == null) {
    315                     Log.w(TAG, "No preference context, skip adding print jobs");
    316                     return;
    317                 }
    318 
    319                 for (PrintJobInfo printJob : printJobs) {
    320                     Preference preference = new Preference(context);
    321 
    322                     preference.setPersistent(false);
    323                     preference.setFragment(PrintJobSettingsFragment.class.getName());
    324                     preference.setKey(printJob.getId().flattenToString());
    325 
    326                     switch (printJob.getState()) {
    327                         case PrintJobInfo.STATE_QUEUED:
    328                         case PrintJobInfo.STATE_STARTED:
    329                             if (!printJob.isCancelling()) {
    330                                 preference.setTitle(getString(
    331                                         R.string.print_printing_state_title_template,
    332                                         printJob.getLabel()));
    333                             } else {
    334                                 preference.setTitle(getString(
    335                                         R.string.print_cancelling_state_title_template,
    336                                         printJob.getLabel()));
    337                             }
    338                             break;
    339                         case PrintJobInfo.STATE_FAILED:
    340                             preference.setTitle(getString(
    341                                     R.string.print_failed_state_title_template,
    342                                     printJob.getLabel()));
    343                             break;
    344                         case PrintJobInfo.STATE_BLOCKED:
    345                             if (!printJob.isCancelling()) {
    346                                 preference.setTitle(getString(
    347                                         R.string.print_blocked_state_title_template,
    348                                         printJob.getLabel()));
    349                             } else {
    350                                 preference.setTitle(getString(
    351                                         R.string.print_cancelling_state_title_template,
    352                                         printJob.getLabel()));
    353                             }
    354                             break;
    355                     }
    356 
    357                     preference.setSummary(getString(R.string.print_job_summary,
    358                             printJob.getPrinterName(), DateUtils.formatSameDayTime(
    359                                     printJob.getCreationTime(), printJob.getCreationTime(),
    360                                     DateFormat.SHORT, DateFormat.SHORT)));
    361 
    362                     switch (printJob.getState()) {
    363                         case PrintJobInfo.STATE_QUEUED:
    364                         case PrintJobInfo.STATE_STARTED:
    365                             preference.setIcon(R.drawable.ic_print);
    366                             break;
    367                         case PrintJobInfo.STATE_FAILED:
    368                         case PrintJobInfo.STATE_BLOCKED:
    369                             preference.setIcon(R.drawable.ic_print_error);
    370                             break;
    371                     }
    372 
    373                     Bundle extras = preference.getExtras();
    374                     extras.putString(EXTRA_PRINT_JOB_ID, printJob.getId().flattenToString());
    375 
    376                     mActivePrintJobsCategory.addPreference(preference);
    377                 }
    378             }
    379         }
    380 
    381         @Override
    382         public void onLoaderReset(Loader<List<PrintJobInfo>> loader) {
    383             getPreferenceScreen().removePreference(mActivePrintJobsCategory);
    384         }
    385     }
    386 
    387     private static final class PrintJobsLoader extends AsyncTaskLoader<List<PrintJobInfo>> {
    388 
    389         private static final String LOG_TAG = "PrintJobsLoader";
    390 
    391         private static final boolean DEBUG = false;
    392 
    393         private List<PrintJobInfo> mPrintJobs = new ArrayList<PrintJobInfo>();
    394 
    395         private final PrintManager mPrintManager;
    396 
    397         private PrintJobStateChangeListener mPrintJobStateChangeListener;
    398 
    399         public PrintJobsLoader(Context context) {
    400             super(context);
    401             mPrintManager = ((PrintManager) context.getSystemService(
    402                     Context.PRINT_SERVICE)).getGlobalPrintManagerForUser(
    403                     context.getUserId());
    404         }
    405 
    406         @Override
    407         public void deliverResult(List<PrintJobInfo> printJobs) {
    408             if (isStarted()) {
    409                 super.deliverResult(printJobs);
    410             }
    411         }
    412 
    413         @Override
    414         protected void onStartLoading() {
    415             if (DEBUG) {
    416                 Log.i(LOG_TAG, "onStartLoading()");
    417             }
    418             // If we already have a result, deliver it immediately.
    419             if (!mPrintJobs.isEmpty()) {
    420                 deliverResult(new ArrayList<PrintJobInfo>(mPrintJobs));
    421             }
    422             // Start watching for changes.
    423             if (mPrintJobStateChangeListener == null) {
    424                 mPrintJobStateChangeListener = new PrintJobStateChangeListener() {
    425                     @Override
    426                     public void onPrintJobStateChanged(PrintJobId printJobId) {
    427                         onForceLoad();
    428                     }
    429                 };
    430                 mPrintManager.addPrintJobStateChangeListener(
    431                         mPrintJobStateChangeListener);
    432             }
    433             // If the data changed or we have no data - load it now.
    434             if (mPrintJobs.isEmpty()) {
    435                 onForceLoad();
    436             }
    437         }
    438 
    439         @Override
    440         protected void onStopLoading() {
    441             if (DEBUG) {
    442                 Log.i(LOG_TAG, "onStopLoading()");
    443             }
    444             // Cancel the load in progress if possible.
    445             onCancelLoad();
    446         }
    447 
    448         @Override
    449         protected void onReset() {
    450             if (DEBUG) {
    451                 Log.i(LOG_TAG, "onReset()");
    452             }
    453             // Stop loading.
    454             onStopLoading();
    455             // Clear the cached result.
    456             mPrintJobs.clear();
    457             // Stop watching for changes.
    458             if (mPrintJobStateChangeListener != null) {
    459                 mPrintManager.removePrintJobStateChangeListener(
    460                         mPrintJobStateChangeListener);
    461                 mPrintJobStateChangeListener = null;
    462             }
    463         }
    464 
    465         @Override
    466         public List<PrintJobInfo> loadInBackground() {
    467             List<PrintJobInfo> printJobInfos = null;
    468             List<PrintJob> printJobs = mPrintManager.getPrintJobs();
    469             final int printJobCount = printJobs.size();
    470             for (int i = 0; i < printJobCount; i++) {
    471                 PrintJobInfo printJob = printJobs.get(i).getInfo();
    472                 if (shouldShowToUser(printJob)) {
    473                     if (printJobInfos == null) {
    474                         printJobInfos = new ArrayList<>();
    475                     }
    476                     printJobInfos.add(printJob);
    477                 }
    478             }
    479             return printJobInfos;
    480         }
    481     }
    482 
    483     /**
    484      * Should the print job the shown to the user in the settings app.
    485      *
    486      * @param printJob The print job in question.
    487      * @return true iff the print job should be shown.
    488      */
    489     private static boolean shouldShowToUser(PrintJobInfo printJob) {
    490         switch (printJob.getState()) {
    491             case PrintJobInfo.STATE_QUEUED:
    492             case PrintJobInfo.STATE_STARTED:
    493             case PrintJobInfo.STATE_BLOCKED:
    494             case PrintJobInfo.STATE_FAILED: {
    495                 return true;
    496             }
    497         }
    498         return false;
    499     }
    500 
    501     /**
    502      * Provider for the print settings summary
    503      */
    504     @VisibleForTesting
    505     static class PrintSummaryProvider
    506             implements SummaryLoader.SummaryProvider, PrintJobStateChangeListener {
    507         private final Context mContext;
    508         private final PrintManagerWrapper mPrintManager;
    509         private final SummaryLoader mSummaryLoader;
    510 
    511         /**
    512          * Create a new {@link PrintSummaryProvider}.
    513          *
    514          * @param context       The context this provider is for
    515          * @param summaryLoader The summary load using this provider
    516          */
    517         PrintSummaryProvider(Context context, SummaryLoader summaryLoader,
    518                 PrintManagerWrapper printManager) {
    519             mContext = context;
    520             mSummaryLoader = summaryLoader;
    521             mPrintManager = printManager;
    522         }
    523 
    524         @Override
    525         public void setListening(boolean isListening) {
    526             if (mPrintManager != null) {
    527                 if (isListening) {
    528                     mPrintManager.addPrintJobStateChanegListner(this);
    529                     onPrintJobStateChanged(null);
    530                 } else {
    531                     mPrintManager.removePrintJobStateChangeListener(this);
    532                 }
    533             }
    534         }
    535 
    536         @Override
    537         public void onPrintJobStateChanged(PrintJobId printJobId) {
    538             final List<PrintJob> printJobs = mPrintManager.getPrintJobs();
    539 
    540             int numActivePrintJobs = 0;
    541             if (printJobs != null) {
    542                 for (PrintJob job : printJobs) {
    543                     if (shouldShowToUser(job.getInfo())) {
    544                         numActivePrintJobs++;
    545                     }
    546                 }
    547             }
    548 
    549             if (numActivePrintJobs > 0) {
    550                 mSummaryLoader.setSummary(this, mContext.getResources().getQuantityString(
    551                         R.plurals.print_jobs_summary, numActivePrintJobs, numActivePrintJobs));
    552             } else {
    553                 List<PrintServiceInfo> services =
    554                         mPrintManager.getPrintServices(PrintManager.ENABLED_SERVICES);
    555                 if (services == null || services.isEmpty()) {
    556                     mSummaryLoader.setSummary(this,
    557                             mContext.getString(R.string.print_settings_summary_no_service));
    558                 } else {
    559                     final int count = services.size();
    560                     mSummaryLoader.setSummary(this,
    561                             mContext.getResources().getQuantityString(
    562                                     R.plurals.print_settings_summary, count, count));
    563                 }
    564             }
    565         }
    566 
    567         static class PrintManagerWrapper {
    568 
    569             private final PrintManager mPrintManager;
    570 
    571             PrintManagerWrapper(Context context) {
    572                 mPrintManager = ((PrintManager) context.getSystemService(Context.PRINT_SERVICE))
    573                         .getGlobalPrintManagerForUser(context.getUserId());
    574             }
    575 
    576             public List<PrintServiceInfo> getPrintServices(int selectionFlags) {
    577                 return mPrintManager.getPrintServices(selectionFlags);
    578             }
    579 
    580             public void addPrintJobStateChanegListner(PrintJobStateChangeListener listener) {
    581                 mPrintManager.addPrintJobStateChangeListener(listener);
    582             }
    583 
    584             public void removePrintJobStateChangeListener(PrintJobStateChangeListener listener) {
    585                 mPrintManager.removePrintJobStateChangeListener(listener);
    586             }
    587 
    588             public List<PrintJob> getPrintJobs() {
    589                 return mPrintManager.getPrintJobs();
    590             }
    591         }
    592     }
    593 
    594     /**
    595      * A factory for {@link PrintSummaryProvider providers} the settings app can use to read the
    596      * print summary.
    597      */
    598     public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY =
    599             (activity, summaryLoader) -> new PrintSummaryProvider(activity, summaryLoader,
    600                     new PrintSummaryProvider.PrintManagerWrapper(activity));
    601 
    602     public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
    603             new BaseSearchIndexProvider() {
    604         @Override
    605         public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
    606             List<SearchIndexableRaw> indexables = new ArrayList<SearchIndexableRaw>();
    607 
    608             PackageManager packageManager = context.getPackageManager();
    609             PrintManager printManager = (PrintManager) context.getSystemService(
    610                     Context.PRINT_SERVICE);
    611 
    612             String screenTitle = context.getResources().getString(R.string.print_settings);
    613             SearchIndexableRaw data = new SearchIndexableRaw(context);
    614             data.title = screenTitle;
    615             data.screenTitle = screenTitle;
    616             indexables.add(data);
    617 
    618             // Indexing all services, regardless if enabled. Please note that the index will not be
    619             // updated until this function is called again
    620             List<PrintServiceInfo> services =
    621                     printManager.getPrintServices(PrintManager.ALL_SERVICES);
    622 
    623             if (services != null) {
    624                 final int serviceCount = services.size();
    625                 for (int i = 0; i < serviceCount; i++) {
    626                     PrintServiceInfo service = services.get(i);
    627 
    628                     ComponentName componentName = new ComponentName(
    629                             service.getResolveInfo().serviceInfo.packageName,
    630                             service.getResolveInfo().serviceInfo.name);
    631 
    632                     data = new SearchIndexableRaw(context);
    633                     data.key = componentName.flattenToString();
    634                     data.title = service.getResolveInfo().loadLabel(packageManager).toString();
    635                     data.screenTitle = screenTitle;
    636                     indexables.add(data);
    637                 }
    638             }
    639 
    640             return indexables;
    641         }
    642 
    643         @Override
    644         public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
    645                 boolean enabled) {
    646             List<SearchIndexableResource> indexables = new ArrayList<SearchIndexableResource>();
    647             SearchIndexableResource indexable = new SearchIndexableResource(context);
    648             indexable.xmlResId = R.xml.print_settings;
    649             indexables.add(indexable);
    650             return indexables;
    651         }
    652     };
    653 }
    654