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