Make Print Settings use the new PrintManager.getPrintServices loader

This makes sure that all data always stays up to date.

printer_dropdown_item.xml:
- Reduce the amount of overriden properties

PrintServiceSettingsFragment:
- Instead receiving most data from PrintSettingsFragment have own loader
  and keep data up to date
- Also the updating of the print service state now has a dedicated
  PrintManager call instead of relying of the Settings-ContentObserver
  to transport this information. No more race-conditions, whohoo!

DynamicIndexableContentMonitor:
- To not rewrite too much code the update logic has to live here but the
  reading of the actual data is in PrintSettingsFragment.

Change-Id: I60715cda8952565d7f68cb24fb7da61a37085887
This commit is contained in:
Philip P. Moltmann
2016-02-24 12:11:05 -08:00
parent 52fdd6a058
commit d9779db8c9
6 changed files with 207 additions and 397 deletions

View File

@@ -28,8 +28,6 @@
android:layout_width="40dip" android:layout_width="40dip"
android:layout_height="40dip" android:layout_height="40dip"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_marginTop="8dip"
android:layout_marginBottom="8dip"
android:duplicateParentState="true" android:duplicateParentState="true"
android:contentDescription="@null" android:contentDescription="@null"
android:visibility="invisible"> android:visibility="invisible">
@@ -47,47 +45,42 @@
android:id="@+id/title" android:id="@+id/title"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium" android:textAppearance="?android:attr/textAppearanceListItem"
android:singleLine="true" android:singleLine="true"
android:ellipsize="end" android:ellipsize="end"
android:textIsSelectable="false" android:duplicateParentState="true" />
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:fadingEdge="horizontal"
android:textAlignment="viewStart"
android:textColor="?android:attr/textColorPrimary"
android:duplicateParentState="true">
</TextView>
<TextView <TextView
android:id="@+id/subtitle" android:id="@+id/subtitle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/title" android:layout_below="@id/title"
android:layout_alignParentStart="true" android:textAppearance="?android:attr/textAppearanceListItemSecondary"
android:textAppearance="?android:attr/textAppearanceSmall" android:textColor="?android:attr/textColorSecondary"
android:singleLine="true" android:singleLine="true"
android:ellipsize="end" android:ellipsize="end"
android:textIsSelectable="false"
android:visibility="gone" android:visibility="gone"
android:textColor="?android:attr/textColorSecondary" android:duplicateParentState="true" />
android:textAlignment="viewStart"
android:duplicateParentState="true">
</TextView>
</RelativeLayout> </RelativeLayout>
<ImageView <!-- wrapper for image view to increase the touch target size -->
<LinearLayout
android:id="@+id/more_info" android:id="@+id/more_info"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:visibility="gone">
<ImageView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:paddingLeft="16dip" android:paddingLeft="16dip"
android:contentDescription="@string/printer_info_desc" android:contentDescription="@string/printer_info_desc"
android:src="@drawable/ic_info_outline" android:src="@drawable/ic_info"
android:tint="?android:attr/colorControlNormal" android:tint="?android:attr/colorControlNormal"
android:tintMode="src_in" android:tintMode="src_in" />
android:visibility="gone">
</ImageView> </LinearLayout>
</LinearLayout> </LinearLayout>

View File

@@ -131,6 +131,8 @@ public class SettingsActivity extends SettingsDrawerActivity
private static final String LOG_TAG = "Settings"; private static final String LOG_TAG = "Settings";
private static final int LOADER_ID_INDEXABLE_CONTENT_MONITOR = 1;
// Constants for state save/restore // Constants for state save/restore
private static final String SAVE_KEY_CATEGORIES = ":settings:categories"; private static final String SAVE_KEY_CATEGORIES = ":settings:categories";
private static final String SAVE_KEY_SEARCH_MENU_EXPANDED = ":settings:search_menu_expanded"; private static final String SAVE_KEY_SEARCH_MENU_EXPANDED = ":settings:search_menu_expanded";
@@ -786,7 +788,7 @@ public class SettingsActivity extends SettingsDrawerActivity
registerReceiver(mUserAddRemoveReceiver, new IntentFilter(Intent.ACTION_USER_ADDED)); registerReceiver(mUserAddRemoveReceiver, new IntentFilter(Intent.ACTION_USER_ADDED));
registerReceiver(mUserAddRemoveReceiver, new IntentFilter(Intent.ACTION_USER_REMOVED)); registerReceiver(mUserAddRemoveReceiver, new IntentFilter(Intent.ACTION_USER_REMOVED));
mDynamicIndexableContentMonitor.register(this); mDynamicIndexableContentMonitor.register(this, LOADER_ID_INDEXABLE_CONTENT_MONITOR);
if(mDisplaySearch && !TextUtils.isEmpty(mSearchQuery)) { if(mDisplaySearch && !TextUtils.isEmpty(mSearchQuery)) {
onQueryTextSubmit(mSearchQuery); onQueryTextSubmit(mSearchQuery);

View File

@@ -19,25 +19,23 @@ package com.android.settings.print;
import android.app.Activity; import android.app.Activity;
import android.app.LoaderManager; import android.app.LoaderManager;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentSender.SendIntentException; import android.content.IntentSender.SendIntentException;
import android.content.Loader; import android.content.Loader;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.database.ContentObserver;
import android.database.DataSetObserver; import android.database.DataSetObserver;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.print.PrintManager; import android.print.PrintManager;
import android.print.PrintServicesLoader;
import android.print.PrinterDiscoverySession; import android.print.PrinterDiscoverySession;
import android.print.PrinterDiscoverySession.OnPrintersChangeListener; import android.print.PrinterDiscoverySession.OnPrintersChangeListener;
import android.print.PrinterId; import android.print.PrinterId;
import android.print.PrinterInfo; import android.print.PrinterInfo;
import android.printservice.PrintServiceInfo;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.util.TypedValue; import android.util.TypedValue;
@@ -53,6 +51,7 @@ import android.widget.BaseAdapter;
import android.widget.Filter; import android.widget.Filter;
import android.widget.Filterable; import android.widget.Filterable;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView; import android.widget.ListView;
import android.widget.SearchView; import android.widget.SearchView;
import android.widget.Switch; import android.widget.Switch;
@@ -74,19 +73,13 @@ import java.util.Map;
* Fragment with print service settings. * Fragment with print service settings.
*/ */
public class PrintServiceSettingsFragment extends SettingsPreferenceFragment public class PrintServiceSettingsFragment extends SettingsPreferenceFragment
implements SwitchBar.OnSwitchChangeListener { implements SwitchBar.OnSwitchChangeListener,
LoaderManager.LoaderCallbacks<List<PrintServiceInfo>> {
private static final String LOG_TAG = "PrintServiceSettingsFragment"; private static final String LOG_TAG = "PrintServiceSettingsFragment";
private static final int LOADER_ID_PRINTERS_LOADER = 1; private static final int LOADER_ID_PRINTERS_LOADER = 1;
private static final int LOADER_ID_PRINT_SERVICE_LOADER = 2;
private final SettingsContentObserver mSettingsContentObserver =
new SettingsContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange, Uri uri) {
updateUiForServiceState();
}
};
private final DataSetObserver mDataObserver = new DataSetObserver() { private final DataSetObserver mDataObserver = new DataSetObserver() {
@Override @Override
@@ -115,10 +108,8 @@ public class PrintServiceSettingsFragment extends SettingsPreferenceFragment
private String mPreferenceKey; private String mPreferenceKey;
private CharSequence mSettingsTitle;
private Intent mSettingsIntent; private Intent mSettingsIntent;
private CharSequence mAddPrintersTitle;
private Intent mAddPrintersIntent; private Intent mAddPrintersIntent;
private ComponentName mComponentName; private ComponentName mComponentName;
@@ -144,6 +135,8 @@ public class PrintServiceSettingsFragment extends SettingsPreferenceFragment
public void onCreate(Bundle icicle) { public void onCreate(Bundle icicle) {
super.onCreate(icicle); super.onCreate(icicle);
mServiceEnabled = getArguments().getBoolean(PrintSettingsFragment.EXTRA_CHECKED);
String title = getArguments().getString(PrintSettingsFragment.EXTRA_TITLE); String title = getArguments().getString(PrintSettingsFragment.EXTRA_TITLE);
if (!TextUtils.isEmpty(title)) { if (!TextUtils.isEmpty(title)) {
getActivity().setTitle(title); getActivity().setTitle(title);
@@ -153,8 +146,6 @@ public class PrintServiceSettingsFragment extends SettingsPreferenceFragment
@Override @Override
public void onStart() { public void onStart() {
super.onStart(); super.onStart();
mSettingsContentObserver.register(getContentResolver());
updateEmptyView(); updateEmptyView();
updateUiForServiceState(); updateUiForServiceState();
} }
@@ -169,7 +160,6 @@ public class PrintServiceSettingsFragment extends SettingsPreferenceFragment
@Override @Override
public void onStop() { public void onStop() {
mSettingsContentObserver.unregister(getContentResolver());
super.onStop(); super.onStop();
} }
@@ -192,14 +182,8 @@ public class PrintServiceSettingsFragment extends SettingsPreferenceFragment
} }
private void onPreferenceToggled(String preferenceKey, boolean enabled) { private void onPreferenceToggled(String preferenceKey, boolean enabled) {
ComponentName service = ComponentName.unflattenFromString(preferenceKey); ((PrintManager)getContext().getSystemService(Context.PRINT_SERVICE))
List<ComponentName> services = PrintSettingsUtils.readDisabledPrintServices(getActivity()); .setPrintServiceEnabled(mComponentName, enabled);
if (enabled) {
services.remove(service);
} else {
services.add(service);
}
PrintSettingsUtils.writeDisabledPrintServices(getActivity(), services);
} }
private ListView getBackupListView() { private ListView getBackupListView() {
@@ -255,9 +239,6 @@ public class PrintServiceSettingsFragment extends SettingsPreferenceFragment
} }
private void updateUiForServiceState() { private void updateUiForServiceState() {
List<ComponentName> disabledServices = PrintSettingsUtils
.readDisabledPrintServices(getActivity());
mServiceEnabled = !disabledServices.contains(mComponentName);
if (mServiceEnabled) { if (mServiceEnabled) {
mSwitchBar.setCheckedInternal(true); mSwitchBar.setCheckedInternal(true);
mPrintersAdapter.enable(); mPrintersAdapter.enable();
@@ -315,56 +296,87 @@ public class PrintServiceSettingsFragment extends SettingsPreferenceFragment
private void updateUiForArguments() { private void updateUiForArguments() {
Bundle arguments = getArguments(); Bundle arguments = getArguments();
// Component name.
mComponentName = ComponentName.unflattenFromString(arguments
.getString(PrintSettingsFragment.EXTRA_SERVICE_COMPONENT_NAME));
// Key. // Key.
mPreferenceKey = arguments.getString(PrintSettingsFragment.EXTRA_PREFERENCE_KEY); mPreferenceKey = mComponentName.flattenToString();
// Enabled. // Enabled.
final boolean enabled = arguments.getBoolean(PrintSettingsFragment.EXTRA_CHECKED); final boolean enabled = arguments.getBoolean(PrintSettingsFragment.EXTRA_CHECKED);
mSwitchBar.setCheckedInternal(enabled); mSwitchBar.setCheckedInternal(enabled);
// Settings title and intent. getLoaderManager().initLoader(LOADER_ID_PRINT_SERVICE_LOADER, null, this);
String settingsTitle = arguments.getString(PrintSettingsFragment.EXTRA_SETTINGS_TITLE); setHasOptionsMenu(true);
String settingsComponentName = arguments.getString( }
PrintSettingsFragment.EXTRA_SETTINGS_COMPONENT_NAME);
if (!TextUtils.isEmpty(settingsTitle) && !TextUtils.isEmpty(settingsComponentName)) { @Override
public Loader<List<PrintServiceInfo>> onCreateLoader(int id, Bundle args) {
return new PrintServicesLoader(
(PrintManager) getContext().getSystemService(Context.PRINT_SERVICE), getContext(),
PrintManager.ALL_SERVICES);
}
@Override
public void onLoadFinished(Loader<List<PrintServiceInfo>> loader,
List<PrintServiceInfo> services) {
PrintServiceInfo service = null;
if (services != null) {
final int numServices = services.size();
for (int i = 0; i < numServices; i++) {
if (services.get(i).getComponentName().equals(mComponentName)) {
service = services.get(i);
break;
}
}
}
if (service == null) {
// The print service was uninstalled
finishFragment();
}
mServiceEnabled = service.isEnabled();
if (service.getSettingsActivityName() != null) {
Intent settingsIntent = new Intent(Intent.ACTION_MAIN).setComponent( Intent settingsIntent = new Intent(Intent.ACTION_MAIN).setComponent(
ComponentName.unflattenFromString(settingsComponentName.toString())); ComponentName.unflattenFromString(service.getSettingsActivityName()));
List<ResolveInfo> resolvedActivities = getPackageManager().queryIntentActivities( List<ResolveInfo> resolvedActivities = getPackageManager().queryIntentActivities(
settingsIntent, 0); settingsIntent, 0);
if (!resolvedActivities.isEmpty()) { if (!resolvedActivities.isEmpty()) {
// The activity is a component name, therefore it is one or none. // The activity is a component name, therefore it is one or none.
if (resolvedActivities.get(0).activityInfo.exported) { if (resolvedActivities.get(0).activityInfo.exported) {
mSettingsTitle = settingsTitle;
mSettingsIntent = settingsIntent; mSettingsIntent = settingsIntent;
} }
} }
} else {
mSettingsIntent = null;
} }
// Add printers title and intent. if (service.getAddPrintersActivityName() != null) {
String addPrintersTitle = arguments.getString( Intent addPrintersIntent = new Intent(Intent.ACTION_MAIN)
PrintSettingsFragment.EXTRA_ADD_PRINTERS_TITLE); .setComponent(ComponentName.unflattenFromString(
String addPrintersComponentName = service.getAddPrintersActivityName()));
arguments.getString(PrintSettingsFragment.EXTRA_ADD_PRINTERS_COMPONENT_NAME);
if (!TextUtils.isEmpty(addPrintersTitle)
&& !TextUtils.isEmpty(addPrintersComponentName)) {
Intent addPritnersIntent = new Intent(Intent.ACTION_MAIN).setComponent(
ComponentName.unflattenFromString(addPrintersComponentName.toString()));
List<ResolveInfo> resolvedActivities = getPackageManager().queryIntentActivities( List<ResolveInfo> resolvedActivities = getPackageManager().queryIntentActivities(
addPritnersIntent, 0); addPrintersIntent, 0);
if (!resolvedActivities.isEmpty()) { if (!resolvedActivities.isEmpty()) {
// The activity is a component name, therefore it is one or none. // The activity is a component name, therefore it is one or none.
if (resolvedActivities.get(0).activityInfo.exported) { if (resolvedActivities.get(0).activityInfo.exported) {
mAddPrintersTitle = addPrintersTitle; mAddPrintersIntent = addPrintersIntent;
mAddPrintersIntent = addPritnersIntent;
} }
} }
} else {
mAddPrintersIntent = null;
} }
// Component name. updateUiForServiceState();
mComponentName = ComponentName.unflattenFromString(arguments }
.getString(PrintSettingsFragment.EXTRA_SERVICE_COMPONENT_NAME));
setHasOptionsMenu(true); @Override
public void onLoaderReset(Loader<List<PrintServiceInfo>> loader) {
updateUiForServiceState();
} }
@Override @Override
@@ -373,16 +385,14 @@ public class PrintServiceSettingsFragment extends SettingsPreferenceFragment
inflater.inflate(R.menu.print_service_settings, menu); inflater.inflate(R.menu.print_service_settings, menu);
MenuItem addPrinters = menu.findItem(R.id.print_menu_item_add_printer); MenuItem addPrinters = menu.findItem(R.id.print_menu_item_add_printer);
if (mServiceEnabled && !TextUtils.isEmpty(mAddPrintersTitle) if (mServiceEnabled && mAddPrintersIntent != null) {
&& mAddPrintersIntent != null) {
addPrinters.setIntent(mAddPrintersIntent); addPrinters.setIntent(mAddPrintersIntent);
} else { } else {
menu.removeItem(R.id.print_menu_item_add_printer); menu.removeItem(R.id.print_menu_item_add_printer);
} }
MenuItem settings = menu.findItem(R.id.print_menu_item_settings); MenuItem settings = menu.findItem(R.id.print_menu_item_settings);
if (mServiceEnabled && !TextUtils.isEmpty(mSettingsTitle) if (mServiceEnabled && mSettingsIntent != null) {
&& mSettingsIntent != null) {
settings.setIntent(mSettingsIntent); settings.setIntent(mSettingsIntent);
} else { } else {
menu.removeItem(R.id.print_menu_item_settings); menu.removeItem(R.id.print_menu_item_settings);
@@ -426,25 +436,6 @@ public class PrintServiceSettingsFragment extends SettingsPreferenceFragment
} }
} }
private static abstract class SettingsContentObserver extends ContentObserver {
public SettingsContentObserver(Handler handler) {
super(handler);
}
public void register(ContentResolver contentResolver) {
contentResolver.registerContentObserver(android.provider.Settings.Secure.getUriFor(
android.provider.Settings.Secure.DISABLED_PRINT_SERVICES), false, this);
}
public void unregister(ContentResolver contentResolver) {
contentResolver.unregisterContentObserver(this);
}
@Override
public abstract void onChange(boolean selfChange, Uri uri);
}
private final class PrintersAdapter extends BaseAdapter private final class PrintersAdapter extends BaseAdapter
implements LoaderManager.LoaderCallbacks<List<PrinterInfo>>, Filterable { implements LoaderManager.LoaderCallbacks<List<PrinterInfo>>, Filterable {
private final Object mLock = new Object(); private final Object mLock = new Object();
@@ -568,7 +559,7 @@ public class PrintServiceSettingsFragment extends SettingsPreferenceFragment
subtitleView.setVisibility(View.GONE); subtitleView.setVisibility(View.GONE);
} }
ImageView moreInfoView = (ImageView) convertView.findViewById(R.id.more_info); LinearLayout moreInfoView = (LinearLayout) convertView.findViewById(R.id.more_info);
if (printer.getInfoIntent() != null) { if (printer.getInfoIntent() != null) {
moreInfoView.setVisibility(View.VISIBLE); moreInfoView.setVisibility(View.VISIBLE);
moreInfoView.setOnClickListener(new OnClickListener() { moreInfoView.setOnClickListener(new OnClickListener() {

View File

@@ -21,23 +21,19 @@ import android.app.LoaderManager.LoaderCallbacks;
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException;
import android.content.AsyncTaskLoader; import android.content.AsyncTaskLoader;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.Loader; import android.content.Loader;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.ContentObserver;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.print.PrintJob; import android.print.PrintJob;
import android.print.PrintJobId; import android.print.PrintJobId;
import android.print.PrintJobInfo; import android.print.PrintJobInfo;
import android.print.PrintManager; import android.print.PrintManager;
import android.print.PrintManager.PrintJobStateChangeListener; import android.print.PrintManager.PrintJobStateChangeListener;
import android.print.PrintServicesLoader;
import android.printservice.PrintServiceInfo; import android.printservice.PrintServiceInfo;
import android.provider.SearchIndexableResource; import android.provider.SearchIndexableResource;
import android.provider.Settings; import android.provider.Settings;
@@ -53,7 +49,6 @@ import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
import android.widget.TextView; import android.widget.TextView;
import com.android.internal.content.PackageMonitor;
import com.android.internal.logging.MetricsProto.MetricsEvent; import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.settings.DialogCreatable; import com.android.settings.DialogCreatable;
import com.android.settings.R; import com.android.settings.R;
@@ -74,18 +69,13 @@ public class PrintSettingsFragment extends ProfileSettingsPreferenceFragment
implements DialogCreatable, Indexable, OnClickListener { implements DialogCreatable, Indexable, OnClickListener {
public static final String TAG = "PrintSettingsFragment"; public static final String TAG = "PrintSettingsFragment";
private static final int LOADER_ID_PRINT_JOBS_LOADER = 1; private static final int LOADER_ID_PRINT_JOBS_LOADER = 1;
private static final int LOADER_ID_PRINT_SERVICES = 2;
private static final String PRINT_JOBS_CATEGORY = "print_jobs_category"; private static final String PRINT_JOBS_CATEGORY = "print_jobs_category";
private static final String PRINT_SERVICES_CATEGORY = "print_services_category"; private static final String PRINT_SERVICES_CATEGORY = "print_services_category";
// Extras passed to sub-fragments.
static final String EXTRA_PREFERENCE_KEY = "EXTRA_PREFERENCE_KEY";
static final String EXTRA_CHECKED = "EXTRA_CHECKED"; static final String EXTRA_CHECKED = "EXTRA_CHECKED";
static final String EXTRA_TITLE = "EXTRA_TITLE"; static final String EXTRA_TITLE = "EXTRA_TITLE";
static final String EXTRA_SETTINGS_TITLE = "EXTRA_SETTINGS_TITLE";
static final String EXTRA_SETTINGS_COMPONENT_NAME = "EXTRA_SETTINGS_COMPONENT_NAME";
static final String EXTRA_ADD_PRINTERS_TITLE = "EXTRA_ADD_PRINTERS_TITLE";
static final String EXTRA_ADD_PRINTERS_COMPONENT_NAME = "EXTRA_ADD_PRINTERS_COMPONENT_NAME";
static final String EXTRA_SERVICE_COMPONENT_NAME = "EXTRA_SERVICE_COMPONENT_NAME"; static final String EXTRA_SERVICE_COMPONENT_NAME = "EXTRA_SERVICE_COMPONENT_NAME";
static final String EXTRA_PRINT_JOB_ID = "EXTRA_PRINT_JOB_ID"; static final String EXTRA_PRINT_JOB_ID = "EXTRA_PRINT_JOB_ID";
@@ -93,29 +83,14 @@ public class PrintSettingsFragment extends ProfileSettingsPreferenceFragment
private static final String EXTRA_PRINT_SERVICE_COMPONENT_NAME = private static final String EXTRA_PRINT_SERVICE_COMPONENT_NAME =
"EXTRA_PRINT_SERVICE_COMPONENT_NAME"; "EXTRA_PRINT_SERVICE_COMPONENT_NAME";
private static final int ORDER_LAST = 1000; private static final int ORDER_LAST = Preference.DEFAULT_ORDER - 1;
private final PackageMonitor mSettingsPackageMonitor = new SettingsPackageMonitor();
private final Handler mHandler = new Handler() {
@Override
public void dispatchMessage(Message msg) {
updateServicesPreferences();
}
};
private final SettingsContentObserver mSettingsContentObserver =
new SettingsContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange, Uri uri) {
updateServicesPreferences();
}
};
private PreferenceCategory mActivePrintJobsCategory; private PreferenceCategory mActivePrintJobsCategory;
private PreferenceCategory mPrintServicesCategory; private PreferenceCategory mPrintServicesCategory;
private PrintJobsController mPrintJobsController; private PrintJobsController mPrintJobsController;
private PrintServicesController mPrintServicesController;
private Button mAddNewServiceButton; private Button mAddNewServiceButton;
@Override @Override
@@ -140,24 +115,23 @@ public class PrintSettingsFragment extends ProfileSettingsPreferenceFragment
getPreferenceScreen().removePreference(mActivePrintJobsCategory); getPreferenceScreen().removePreference(mActivePrintJobsCategory);
mPrintJobsController = new PrintJobsController(); mPrintJobsController = new PrintJobsController();
getActivity().getLoaderManager().initLoader(LOADER_ID_PRINT_JOBS_LOADER, getActivity().getLoaderManager().initLoader(LOADER_ID_PRINT_JOBS_LOADER, null,
null, mPrintJobsController); mPrintJobsController);
mPrintServicesController = new PrintServicesController();
getActivity().getLoaderManager().initLoader(LOADER_ID_PRINT_SERVICES, null,
mPrintServicesController);
} }
@Override @Override
public void onStart() { public void onStart() {
super.onStart(); super.onStart();
mSettingsPackageMonitor.register(getActivity(), getActivity().getMainLooper(), false);
mSettingsContentObserver.register(getContentResolver());
updateServicesPreferences();
setHasOptionsMenu(true); setHasOptionsMenu(true);
startSubSettingsIfNeeded(); startSubSettingsIfNeeded();
} }
@Override @Override
public void onStop() { public void onStop() {
mSettingsPackageMonitor.unregister();
mSettingsContentObserver.unregister(getContentResolver());
super.onStop(); super.onStop();
} }
@@ -187,95 +161,81 @@ public class PrintSettingsFragment extends ProfileSettingsPreferenceFragment
return Settings.ACTION_PRINT_SETTINGS; return Settings.ACTION_PRINT_SETTINGS;
} }
private void updateServicesPreferences() { /**
if (getPreferenceScreen().findPreference(PRINT_SERVICES_CATEGORY) == null) { * Adds preferences for all print services to the {@value PRINT_SERVICES_CATEGORY} cathegory.
getPreferenceScreen().addPreference(mPrintServicesCategory); */
private final class PrintServicesController implements
LoaderCallbacks<List<PrintServiceInfo>> {
@Override
public Loader<List<PrintServiceInfo>> onCreateLoader(int id, Bundle args) {
PrintManager printManager =
(PrintManager) getContext().getSystemService(Context.PRINT_SERVICE);
if (printManager != null) {
return new PrintServicesLoader(printManager, getContext(),
PrintManager.ALL_SERVICES);
} else { } else {
// Since services category is auto generated we have to do a pass return null;
// to generate it since services can come and go. }
mPrintServicesCategory.removeAll();
} }
List<ComponentName> disabledServices = PrintSettingsUtils @Override
.readDisabledPrintServices(getActivity()); public void onLoadFinished(Loader<List<PrintServiceInfo>> loader,
List<PrintServiceInfo> services) {
if (services.isEmpty()) {
getPreferenceScreen().removePreference(mPrintServicesCategory);
return;
} else if (getPreferenceScreen().findPreference(PRINT_SERVICES_CATEGORY) == null) {
getPreferenceScreen().addPreference(mPrintServicesCategory);
}
final PackageManager pm = getActivity().getPackageManager(); mPrintServicesCategory.removeAll();
PackageManager pm = getActivity().getPackageManager();
List<ResolveInfo> installedServices = pm
.queryIntentServices(
new Intent(android.printservice.PrintService.SERVICE_INTERFACE),
PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
final int installedServiceCount = installedServices.size();
for (int i = 0; i < installedServiceCount; i++) {
ResolveInfo installedService = installedServices.get(i);
final int numServices = services.size();
for (int i = 0; i < numServices; i++) {
PrintServiceInfo service = services.get(i);
PreferenceScreen preference = getPreferenceManager().createPreferenceScreen( PreferenceScreen preference = getPreferenceManager().createPreferenceScreen(
getActivity()); getActivity());
String title = installedService.loadLabel(getPackageManager()).toString(); String title = service.getResolveInfo().loadLabel(pm).toString();
preference.setTitle(title); preference.setTitle(title);
ComponentName componentName = new ComponentName( ComponentName componentName = service.getComponentName();
installedService.serviceInfo.packageName,
installedService.serviceInfo.name);
preference.setKey(componentName.flattenToString()); preference.setKey(componentName.flattenToString());
preference.setOrder(i); preference.setOrder(Math.min(ORDER_LAST - 1, componentName.hashCode()));
preference.setFragment(PrintServiceSettingsFragment.class.getName()); preference.setFragment(PrintServiceSettingsFragment.class.getName());
preference.setPersistent(false); preference.setPersistent(false);
final boolean serviceEnabled = !disabledServices.contains(componentName); if (service.isEnabled()) {
if (serviceEnabled) {
preference.setSummary(getString(R.string.print_feature_state_on)); preference.setSummary(getString(R.string.print_feature_state_on));
} else { } else {
preference.setSummary(getString(R.string.print_feature_state_off)); preference.setSummary(getString(R.string.print_feature_state_off));
} }
final Drawable drawable = installedService.loadIcon(pm); Drawable drawable = service.getResolveInfo().loadIcon(pm);
if (drawable != null) { if (drawable != null) {
preference.setIcon(drawable); preference.setIcon(drawable);
} }
Bundle extras = preference.getExtras(); Bundle extras = preference.getExtras();
extras.putString(EXTRA_PREFERENCE_KEY, preference.getKey()); extras.putBoolean(EXTRA_CHECKED, service.isEnabled());
extras.putBoolean(EXTRA_CHECKED, serviceEnabled);
extras.putString(EXTRA_TITLE, title); extras.putString(EXTRA_TITLE, title);
PrintServiceInfo printServiceInfo = PrintServiceInfo.create(
installedService, getActivity());
String settingsClassName = printServiceInfo.getSettingsActivityName();
if (!TextUtils.isEmpty(settingsClassName)) {
extras.putString(EXTRA_SETTINGS_TITLE,
getString(R.string.print_menu_item_settings));
extras.putString(EXTRA_SETTINGS_COMPONENT_NAME,
new ComponentName(installedService.serviceInfo.packageName,
settingsClassName).flattenToString());
}
String addPrinterClassName = printServiceInfo.getAddPrintersActivityName();
if (!TextUtils.isEmpty(addPrinterClassName)) {
extras.putString(EXTRA_ADD_PRINTERS_TITLE,
getString(R.string.print_menu_item_add_printers));
extras.putString(EXTRA_ADD_PRINTERS_COMPONENT_NAME,
new ComponentName(installedService.serviceInfo.packageName,
addPrinterClassName).flattenToString());
}
extras.putString(EXTRA_SERVICE_COMPONENT_NAME, componentName.flattenToString()); extras.putString(EXTRA_SERVICE_COMPONENT_NAME, componentName.flattenToString());
mPrintServicesCategory.addPreference(preference); mPrintServicesCategory.addPreference(preference);
} }
if (mPrintServicesCategory.getPreferenceCount() == 0) { Preference addNewServicePreference = newAddServicePreferenceOrNull();
getPreferenceScreen().removePreference(mPrintServicesCategory);
} else {
final Preference addNewServicePreference = newAddServicePreferenceOrNull();
if (addNewServicePreference != null) { if (addNewServicePreference != null) {
mPrintServicesCategory.addPreference(addNewServicePreference); mPrintServicesCategory.addPreference(addNewServicePreference);
} }
} }
@Override
public void onLoaderReset(Loader<List<PrintServiceInfo>> loader) {
getPreferenceScreen().removePreference(mPrintServicesCategory);
}
} }
private Preference newAddServicePreferenceOrNull() { private Preference newAddServicePreferenceOrNull() {
@@ -329,47 +289,6 @@ public class PrintSettingsFragment extends ProfileSettingsPreferenceFragment
} }
} }
private class SettingsPackageMonitor extends PackageMonitor {
@Override
public void onPackageAdded(String packageName, int uid) {
mHandler.obtainMessage().sendToTarget();
}
@Override
public void onPackageAppeared(String packageName, int reason) {
mHandler.obtainMessage().sendToTarget();
}
@Override
public void onPackageDisappeared(String packageName, int reason) {
mHandler.obtainMessage().sendToTarget();
}
@Override
public void onPackageRemoved(String packageName, int uid) {
mHandler.obtainMessage().sendToTarget();
}
}
private static abstract class SettingsContentObserver extends ContentObserver {
public SettingsContentObserver(Handler handler) {
super(handler);
}
public void register(ContentResolver contentResolver) {
contentResolver.registerContentObserver(Settings.Secure.getUriFor(
Settings.Secure.DISABLED_PRINT_SERVICES), false, this);
}
public void unregister(ContentResolver contentResolver) {
contentResolver.unregisterContentObserver(this);
}
@Override
public abstract void onChange(boolean selfChange, Uri uri);
}
private final class PrintJobsController implements LoaderCallbacks<List<PrintJobInfo>> { private final class PrintJobsController implements LoaderCallbacks<List<PrintJobInfo>> {
@Override @Override
@@ -661,8 +580,10 @@ public class PrintSettingsFragment extends ProfileSettingsPreferenceFragment
data.screenTitle = screenTitle; data.screenTitle = screenTitle;
indexables.add(data); indexables.add(data);
// Indexing all services, regardless if enabled. // Indexing all services, regardless if enabled. Please note that the index will not be
List<PrintServiceInfo> services = printManager.getInstalledPrintServices(); // updated until this function is called again
List<PrintServiceInfo> services =
printManager.getPrintServices(PrintManager.ALL_SERVICES);
final int serviceCount = services.size(); final int serviceCount = services.size();
for (int i = 0; i < serviceCount; i++) { for (int i = 0; i < serviceCount; i++) {
PrintServiceInfo service = services.get(i); PrintServiceInfo service = services.get(i);

View File

@@ -1,79 +0,0 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.print;
import android.content.ComponentName;
import android.content.Context;
import android.provider.Settings;
import android.text.TextUtils;
import android.text.TextUtils.SimpleStringSplitter;
import java.util.ArrayList;
import java.util.List;
/**
* Helper methods for reading and writing to print settings.
*/
public class PrintSettingsUtils {
private static final char DISABLED_PRINT_SERVICES_SEPARATOR = ':';
private PrintSettingsUtils() {
/* do nothing */
}
public static List<ComponentName> readDisabledPrintServices(Context context) {
List<ComponentName> disabledServices = new ArrayList<ComponentName>();
String disabledServicesSetting = Settings.Secure.getString(context
.getContentResolver(), Settings.Secure.DISABLED_PRINT_SERVICES);
if (TextUtils.isEmpty(disabledServicesSetting)) {
return disabledServices;
}
SimpleStringSplitter colonSplitter = new SimpleStringSplitter(
DISABLED_PRINT_SERVICES_SEPARATOR);
colonSplitter.setString(disabledServicesSetting);
while (colonSplitter.hasNext()) {
String componentNameString = colonSplitter.next();
ComponentName disabledService = ComponentName.unflattenFromString(
componentNameString);
if (disabledService != null) {
disabledServices.add(disabledService);
}
}
return disabledServices;
}
public static void writeDisabledPrintServices(Context context,
List<ComponentName> services) {
StringBuilder builder = new StringBuilder();
final int serviceCount = services.size();
for (int i = 0; i < serviceCount; i++) {
ComponentName service = services.get(i);
if (builder.length() > 0) {
builder.append(DISABLED_PRINT_SERVICES_SEPARATOR);
}
builder.append(service.flattenToString());
}
Settings.Secure.putString(context.getContentResolver(),
Settings.Secure.DISABLED_PRINT_SERVICES,
builder.toString());
}
}

View File

@@ -18,20 +18,24 @@ package com.android.settings.search;
import android.accessibilityservice.AccessibilityService; import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo; import android.accessibilityservice.AccessibilityServiceInfo;
import android.app.Activity;
import android.app.LoaderManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.Loader;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo; import android.content.pm.ServiceInfo;
import android.database.ContentObserver; import android.database.ContentObserver;
import android.hardware.input.InputManager; import android.hardware.input.InputManager;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.os.Message; import android.os.Message;
import android.os.UserHandle; import android.os.UserHandle;
import android.print.PrintManager; import android.print.PrintManager;
import android.printservice.PrintService; import android.print.PrintServicesLoader;
import android.printservice.PrintServiceInfo; import android.printservice.PrintServiceInfo;
import android.provider.UserDictionary; import android.provider.UserDictionary;
import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityManager;
@@ -47,7 +51,8 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
public final class DynamicIndexableContentMonitor extends PackageMonitor implements public final class DynamicIndexableContentMonitor extends PackageMonitor implements
InputManager.InputDeviceListener { InputManager.InputDeviceListener,
LoaderManager.LoaderCallbacks<List<PrintServiceInfo>> {
private static final long DELAY_PROCESS_PACKAGE_CHANGE = 2000; private static final long DELAY_PROCESS_PACKAGE_CHANGE = 2000;
@@ -55,7 +60,6 @@ public final class DynamicIndexableContentMonitor extends PackageMonitor impleme
private static final int MSG_PACKAGE_UNAVAILABLE = 2; private static final int MSG_PACKAGE_UNAVAILABLE = 2;
private final List<String> mAccessibilityServices = new ArrayList<String>(); private final List<String> mAccessibilityServices = new ArrayList<String>();
private final List<String> mPrintServices = new ArrayList<String>();
private final List<String> mImeServices = new ArrayList<String>(); private final List<String> mImeServices = new ArrayList<String>();
private final Handler mHandler = new Handler() { private final Handler mHandler = new Handler() {
@@ -79,7 +83,6 @@ public final class DynamicIndexableContentMonitor extends PackageMonitor impleme
new UserDictionaryContentObserver(mHandler); new UserDictionaryContentObserver(mHandler);
private Context mContext; private Context mContext;
private boolean mHasFeaturePrinting;
private boolean mHasFeatureIme; private boolean mHasFeatureIme;
private static Intent getAccessibilityServiceIntent(String packageName) { private static Intent getAccessibilityServiceIntent(String packageName) {
@@ -88,22 +91,16 @@ public final class DynamicIndexableContentMonitor extends PackageMonitor impleme
return intent; return intent;
} }
private static Intent getPrintServiceIntent(String packageName) {
final Intent intent = new Intent(PrintService.SERVICE_INTERFACE);
intent.setPackage(packageName);
return intent;
}
private static Intent getIMEServiceIntent(String packageName) { private static Intent getIMEServiceIntent(String packageName) {
final Intent intent = new Intent("android.view.InputMethod"); final Intent intent = new Intent("android.view.InputMethod");
intent.setPackage(packageName); intent.setPackage(packageName);
return intent; return intent;
} }
public void register(Context context) { public void register(Activity activity, int loaderId) {
mContext = context; mContext = activity;
mHasFeaturePrinting = mContext.getPackageManager().hasSystemFeature( boolean hasFeaturePrinting = mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_PRINTING); PackageManager.FEATURE_PRINTING);
mHasFeatureIme = mContext.getPackageManager().hasSystemFeature( mHasFeatureIme = mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_INPUT_METHODS); PackageManager.FEATURE_INPUT_METHODS);
@@ -123,20 +120,8 @@ public final class DynamicIndexableContentMonitor extends PackageMonitor impleme
mAccessibilityServices.add(resolveInfo.serviceInfo.packageName); mAccessibilityServices.add(resolveInfo.serviceInfo.packageName);
} }
if (mHasFeaturePrinting) { if (hasFeaturePrinting) {
// Cache print service packages to know when they go away. activity.getLoaderManager().initLoader(loaderId, null, this);
PrintManager printManager = (PrintManager)
mContext.getSystemService(Context.PRINT_SERVICE);
List<PrintServiceInfo> printServices = printManager.getInstalledPrintServices();
final int serviceCount = printServices.size();
for (int i = 0; i < serviceCount; i++) {
PrintServiceInfo printService = printServices.get(i);
ResolveInfo resolveInfo = printService.getResolveInfo();
if (resolveInfo == null || resolveInfo.serviceInfo == null) {
continue;
}
mPrintServices.add(resolveInfo.serviceInfo.packageName);
}
} }
// Cache IME service packages to know when they go away. // Cache IME service packages to know when they go away.
@@ -158,12 +143,12 @@ public final class DynamicIndexableContentMonitor extends PackageMonitor impleme
} }
// Watch for input device changes. // Watch for input device changes.
InputManager inputManager = (InputManager) context.getSystemService( InputManager inputManager = (InputManager) activity.getSystemService(
Context.INPUT_SERVICE); Context.INPUT_SERVICE);
inputManager.registerInputDeviceListener(this, mHandler); inputManager.registerInputDeviceListener(this, mHandler);
// Start tracking packages. // Start tracking packages.
register(context, Looper.getMainLooper(), UserHandle.CURRENT, false); register(activity, Looper.getMainLooper(), UserHandle.CURRENT, false);
} }
public void unregister() { public void unregister() {
@@ -179,7 +164,6 @@ public final class DynamicIndexableContentMonitor extends PackageMonitor impleme
} }
mAccessibilityServices.clear(); mAccessibilityServices.clear();
mPrintServices.clear();
mImeServices.clear(); mImeServices.clear();
} }
@@ -242,18 +226,6 @@ public final class DynamicIndexableContentMonitor extends PackageMonitor impleme
} }
} }
if (mHasFeaturePrinting) {
if (!mPrintServices.contains(packageName)) {
final Intent intent = getPrintServiceIntent(packageName);
List<?> services = mContext.getPackageManager().queryIntentServices(intent, 0);
if (services != null && !services.isEmpty()) {
mPrintServices.add(packageName);
Index.getInstance(mContext).updateFromClassNameResource(
PrintSettingsFragment.class.getName(), false, true);
}
}
}
if (mHasFeatureIme) { if (mHasFeatureIme) {
if (!mImeServices.contains(packageName)) { if (!mImeServices.contains(packageName)) {
Intent intent = getIMEServiceIntent(packageName); Intent intent = getIMEServiceIntent(packageName);
@@ -275,15 +247,6 @@ public final class DynamicIndexableContentMonitor extends PackageMonitor impleme
AccessibilitySettings.class.getName(), true, true); AccessibilitySettings.class.getName(), true, true);
} }
if (mHasFeaturePrinting) {
final int printIndex = mPrintServices.indexOf(packageName);
if (printIndex >= 0) {
mPrintServices.remove(printIndex);
Index.getInstance(mContext).updateFromClassNameResource(
PrintSettingsFragment.class.getName(), true, true);
}
}
if (mHasFeatureIme) { if (mHasFeatureIme) {
final int imeIndex = mImeServices.indexOf(packageName); final int imeIndex = mImeServices.indexOf(packageName);
if (imeIndex >= 0) { if (imeIndex >= 0) {
@@ -294,6 +257,25 @@ public final class DynamicIndexableContentMonitor extends PackageMonitor impleme
} }
} }
@Override
public Loader<List<PrintServiceInfo>> onCreateLoader(int id, Bundle args) {
return new PrintServicesLoader(
(PrintManager) mContext.getSystemService(Context.PRINT_SERVICE), mContext,
PrintManager.ALL_SERVICES);
}
@Override
public void onLoadFinished(Loader<List<PrintServiceInfo>> loader,
List<PrintServiceInfo> services) {
Index.getInstance(mContext).updateFromClassNameResource(
PrintSettingsFragment.class.getName(), false, true);
}
@Override
public void onLoaderReset(Loader<List<PrintServiceInfo>> loader) {
// nothing to do
}
private final class UserDictionaryContentObserver extends ContentObserver { private final class UserDictionaryContentObserver extends ContentObserver {
public UserDictionaryContentObserver(Handler handler) { public UserDictionaryContentObserver(Handler handler) {