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