diff --git a/packages/PrintSpooler/AndroidManifest.xml b/packages/PrintSpooler/AndroidManifest.xml
index 937eb157268c7..af9d25196bec5 100644
--- a/packages/PrintSpooler/AndroidManifest.xml
+++ b/packages/PrintSpooler/AndroidManifest.xml
@@ -38,6 +38,8 @@
+
+
> {
+public final class FusedPrintersProvider extends Loader>
+ implements LocationListener {
private static final String LOG_TAG = "FusedPrintersProvider";
private static final boolean DEBUG = false;
@@ -70,10 +81,22 @@ public final class FusedPrintersProvider extends Loader> {
private static final int MAX_FAVORITE_PRINTER_COUNT = 4;
+ /** Interval of location updated in ms */
+ private static final int LOCATION_UPDATE_MS = 30 * 1000;
+
+ /** Maximum acceptable age of the location in ms */
+ private static final int MAX_LOCATION_AGE_MS = 10 * 60 * 1000;
+
+ /** The worst accuracy that is considered usable in m */
+ private static final int MIN_LOCATION_ACCURACY = 50;
+
+ /** Maximum distance where a printer is still considered "near" */
+ private static final int MAX_PRINTER_DISTANCE = MIN_LOCATION_ACCURACY * 2;
+
private final List mPrinters =
new ArrayList<>();
- private final List mFavoritePrinters =
+ private final List> mFavoritePrinters =
new ArrayList<>();
private final PersistenceManager mPersistenceManager;
@@ -84,33 +107,111 @@ public final class FusedPrintersProvider extends Loader> {
private boolean mPrintersUpdatedBefore;
+ /** Last known location, can be null or out of date */
+ private final Object mLocationLock;
+ private Location mLocation;
+
+ /** Location used when the printers were updated the last time */
+ private Location mLocationOfLastPrinterUpdate;
+
+ /** Reference to the system's location manager */
+ private final LocationManager mLocationManager;
+
+ /**
+ * Get a reference to the current location.
+ */
+ private Location getCurrentLocation() {
+ synchronized (mLocationLock) {
+ return mLocation;
+ }
+ }
+
public FusedPrintersProvider(Context context) {
super(context);
+ mLocationLock = new Object();
mPersistenceManager = new PersistenceManager(context);
+ mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
}
public void addHistoricalPrinter(PrinterInfo printer) {
mPersistenceManager.addPrinterAndWritePrinterHistory(printer);
}
+ /**
+ * Add printer to dest, or if updatedPrinters add the updated printer. If the updated printer
+ * was added, remove it from updatedPrinters.
+ *
+ * @param dest The list the printers should be added to
+ * @param printer The printer to add
+ * @param updatedPrinters The printer to add
+ */
+ private void updateAndAddPrinter(List dest, PrinterInfo printer,
+ Map updatedPrinters) {
+ PrinterInfo updatedPrinter = updatedPrinters.remove(printer.getId());
+ if (updatedPrinter != null) {
+ dest.add(updatedPrinter);
+ } else {
+ dest.add(printer);
+ }
+ }
+
+ /**
+ * Compute the printers, order them appropriately and deliver the printers to the clients. We
+ * prefer printers that have been previously used (favorites) and printers that have been used
+ * previously close to the current location (near printers).
+ *
+ * @param discoveredPrinters All printers currently discovered by the print discovery session.
+ * @param favoritePrinters The ordered list of printers. The earlier in the list, the more
+ * preferred.
+ */
private void computeAndDeliverResult(Map discoveredPrinters,
- List favoritePrinters) {
+ List> favoritePrinters) {
List printers = new ArrayList<>();
- // Add the updated favorite printers.
+ // Store the printerIds that have already been added. We cannot compare the printerInfos in
+ // "printers" as they might have been taken from discoveredPrinters and the printerInfo does
+ // not equals() anymore
+ HashSet alreadyAddedPrinter = new HashSet<>(MAX_FAVORITE_PRINTER_COUNT);
+
+ Location location = getCurrentLocation();
+
+ // Add the favorite printers that have last been used close to the current location
final int favoritePrinterCount = favoritePrinters.size();
- for (int i = 0; i < favoritePrinterCount; i++) {
- PrinterInfo favoritePrinter = favoritePrinters.get(i);
- PrinterInfo updatedPrinter = discoveredPrinters.remove(
- favoritePrinter.getId());
- if (updatedPrinter != null) {
- printers.add(updatedPrinter);
- } else {
- printers.add(favoritePrinter);
+ if (location != null) {
+ for (int i = 0; i < favoritePrinterCount; i++) {
+ // Only add a certain amount of favorite printers
+ if (printers.size() == MAX_FAVORITE_PRINTER_COUNT) {
+ break;
+ }
+
+ PrinterInfo favoritePrinter = favoritePrinters.get(i).first;
+ Location printerLocation = favoritePrinters.get(i).second;
+
+ if (printerLocation != null
+ && !alreadyAddedPrinter.contains(favoritePrinter.getId())) {
+ if (printerLocation.distanceTo(location) <= MAX_PRINTER_DISTANCE) {
+ updateAndAddPrinter(printers, favoritePrinter, discoveredPrinters);
+ alreadyAddedPrinter.add(favoritePrinter.getId());
+ }
+ }
}
}
- // Add other updated printers.
+ // Add the other favorite printers
+ for (int i = 0; i < favoritePrinterCount; i++) {
+ // Only add a certain amount of favorite printers
+ if (printers.size() == MAX_FAVORITE_PRINTER_COUNT) {
+ break;
+ }
+
+ PrinterInfo favoritePrinter = favoritePrinters.get(i).first;
+ if (!alreadyAddedPrinter.contains(favoritePrinter.getId())) {
+ updateAndAddPrinter(printers, favoritePrinter, discoveredPrinters);
+ }
+ }
+
+ // Add other updated printers. Printers that have already been added have been removed from
+ // discoveredPrinters in the calls to updateAndAddPrinter
final int printerCount = mPrinters.size();
for (int i = 0; i < printerCount; i++) {
PrinterInfo printer = mPrinters.get(i);
@@ -142,6 +243,21 @@ public final class FusedPrintersProvider extends Loader> {
if (DEBUG) {
Log.i(LOG_TAG, "onStartLoading() " + FusedPrintersProvider.this.hashCode());
}
+
+ mLocationManager.requestLocationUpdates(LocationRequest.create()
+ .setQuality(LocationRequest.POWER_LOW).setInterval(LOCATION_UPDATE_MS), this,
+ Looper.getMainLooper());
+
+ Location lastLocation = mLocationManager.getLastLocation();
+ if (lastLocation != null) {
+ onLocationChanged(lastLocation);
+ }
+
+ // Jumpstart location with a single forced update
+ Criteria oneTimeCriteria = new Criteria();
+ oneTimeCriteria.setAccuracy(Criteria.ACCURACY_FINE);
+ mLocationManager.requestSingleUpdate(oneTimeCriteria, this, Looper.getMainLooper());
+
// The contract is that if we already have a valid,
// result the we have to deliver it immediately.
if (!mPrinters.isEmpty()) {
@@ -158,6 +274,8 @@ public final class FusedPrintersProvider extends Loader> {
Log.i(LOG_TAG, "onStopLoading() " + FusedPrintersProvider.this.hashCode());
}
onCancelLoad();
+
+ mLocationManager.removeUpdates(this);
}
@Override
@@ -188,28 +306,32 @@ public final class FusedPrintersProvider extends Loader> {
+ " " + FusedPrintersProvider.this.hashCode());
}
- updatePrinters(mDiscoverySession.getPrinters(), mFavoritePrinters);
+ updatePrinters(mDiscoverySession.getPrinters(), mFavoritePrinters,
+ getCurrentLocation());
}
});
final int favoriteCount = mFavoritePrinters.size();
List printerIds = new ArrayList<>(favoriteCount);
for (int i = 0; i < favoriteCount; i++) {
- printerIds.add(mFavoritePrinters.get(i).getId());
+ printerIds.add(mFavoritePrinters.get(i).first.getId());
}
mDiscoverySession.startPrinterDiscovery(printerIds);
List printers = mDiscoverySession.getPrinters();
- if (!printers.isEmpty()) {
- updatePrinters(printers, mFavoritePrinters);
- }
+
+ updatePrinters(printers, mFavoritePrinters, getCurrentLocation());
}
}
- private void updatePrinters(List printers, List favoritePrinters) {
+ private void updatePrinters(List printers,
+ List> favoritePrinters,
+ Location location) {
if (mPrintersUpdatedBefore && mPrinters.equals(printers)
- && mFavoritePrinters.equals(favoritePrinters)) {
+ && mFavoritePrinters.equals(favoritePrinters)
+ && Objects.equals(mLocationOfLastPrinterUpdate, location)) {
return;
}
+ mLocationOfLastPrinterUpdate = location;
mPrintersUpdatedBefore = true;
// Some of the found printers may have be a printer that is in the
@@ -271,6 +393,60 @@ public final class FusedPrintersProvider extends Loader> {
onStopLoading();
}
+ /**
+ * Check if the location is acceptable. This is to filter out excessively old or inaccurate
+ * location updates.
+ *
+ * @param location the location to check
+ * @return true iff the location is usable.
+ */
+ private boolean isLocationAcceptable(Location location) {
+ return location != null
+ && location.getElapsedRealtimeNanos() > SystemClock.elapsedRealtimeNanos()
+ - MAX_LOCATION_AGE_MS * 1000_000L
+ && location.hasAccuracy()
+ && location.getAccuracy() < MIN_LOCATION_ACCURACY;
+ }
+
+ @Override
+ public void onLocationChanged(Location location) {
+ synchronized(mLocationLock) {
+ // We expect the user to not move too fast while printing. Hence prefer more accurate
+ // updates over more recent ones for LOCATION_UPDATE_MS. We add a 10% fudge factor here
+ // as the location provider might send an update slightly too early.
+ if (isLocationAcceptable(location)
+ && !location.equals(mLocation)
+ && (mLocation == null
+ || location
+ .getElapsedRealtimeNanos() > mLocation.getElapsedRealtimeNanos()
+ + LOCATION_UPDATE_MS * 0.9 * 1000_000L
+ || (!mLocation.hasAccuracy()
+ || location.getAccuracy() < mLocation.getAccuracy()))) {
+ // Other callers of updatePrinters might want to know the location, hence cache it
+ mLocation = location;
+
+ if (areHistoricalPrintersLoaded()) {
+ updatePrinters(mDiscoverySession.getPrinters(), mFavoritePrinters, mLocation);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onStatusChanged(String provider, int status, Bundle extras) {
+ // nothing to do
+ }
+
+ @Override
+ public void onProviderEnabled(String provider) {
+ // nothing to do
+ }
+
+ @Override
+ public void onProviderDisabled(String provider) {
+ // nothing to do
+ }
+
public boolean areHistoricalPrintersLoaded() {
return mPersistenceManager.mReadHistoryCompleted;
}
@@ -294,7 +470,7 @@ public final class FusedPrintersProvider extends Loader> {
public boolean isFavoritePrinter(PrinterId printerId) {
final int printerCount = mFavoritePrinters.size();
for (int i = 0; i < printerCount; i++) {
- PrinterInfo favoritePritner = mFavoritePrinters.get(i);
+ PrinterInfo favoritePritner = mFavoritePrinters.get(i).first;
if (favoritePritner.getId().equals(printerId)) {
return true;
}
@@ -303,28 +479,22 @@ public final class FusedPrintersProvider extends Loader> {
}
public void forgetFavoritePrinter(PrinterId printerId) {
- List newFavoritePrinters = null;
+ final int favoritePrinterCount = mFavoritePrinters.size();
+ List> newFavoritePrinters = new ArrayList<>(
+ favoritePrinterCount - 1);
// Remove the printer from the favorites.
- final int favoritePrinterCount = mFavoritePrinters.size();
for (int i = 0; i < favoritePrinterCount; i++) {
- PrinterInfo favoritePrinter = mFavoritePrinters.get(i);
- if (favoritePrinter.getId().equals(printerId)) {
- newFavoritePrinters = new ArrayList<>();
- newFavoritePrinters.addAll(mPrinters);
- newFavoritePrinters.remove(i);
- break;
+ if (!mFavoritePrinters.get(i).first.getId().equals(printerId)) {
+ newFavoritePrinters.add(mFavoritePrinters.get(i));
}
}
- // If we removed a favorite printer, we have work to do.
- if (newFavoritePrinters != null) {
- // Remove the printer from history and persist the latter.
- mPersistenceManager.removeHistoricalPrinterAndWritePrinterHistory(printerId);
+ // Remove the printer from history and persist the latter.
+ mPersistenceManager.removeHistoricalPrinterAndWritePrinterHistory(printerId);
- // Recompute and deliver the printers.
- updatePrinters(mDiscoverySession.getPrinters(), newFavoritePrinters);
- }
+ // Recompute and deliver the printers.
+ updatePrinters(mDiscoverySession.getPrinters(), newFavoritePrinters, getCurrentLocation());
}
private final class PersistenceManager {
@@ -333,17 +503,22 @@ public final class FusedPrintersProvider extends Loader> {
private static final String TAG_PRINTERS = "printers";
private static final String TAG_PRINTER = "printer";
+ private static final String TAG_LOCATION = "location";
private static final String TAG_PRINTER_ID = "printerId";
private static final String ATTR_LOCAL_ID = "localId";
private static final String ATTR_SERVICE_NAME = "serviceName";
+ private static final String ATTR_LONGITUDE = "longitude";
+ private static final String ATTR_LATITUDE = "latitude";
+ private static final String ATTR_ACCURACY = "accuracy";
+
private static final String ATTR_NAME = "name";
private static final String ATTR_DESCRIPTION = "description";
private final AtomicFile mStatePersistFile;
- private List mHistoricalPrinters = new ArrayList<>();
+ private List> mHistoricalPrinters = new ArrayList<>();
private boolean mReadHistoryCompleted;
@@ -402,7 +577,7 @@ public final class FusedPrintersProvider extends Loader> {
boolean writeHistory = false;
final int printerCount = mHistoricalPrinters.size();
for (int i = 0; i < printerCount; i++) {
- PrinterInfo historicalPrinter = mHistoricalPrinters.get(i);
+ PrinterInfo historicalPrinter = mHistoricalPrinters.get(i).first;
if (!historicalPrinter.getId().equals(printer.getId())) {
continue;
@@ -414,7 +589,8 @@ public final class FusedPrintersProvider extends Loader> {
continue;
}
- mHistoricalPrinters.set(i, printer);
+ mHistoricalPrinters.set(i, new Pair(printer,
+ mHistoricalPrinters.get(i).second));
// We only persist limited information in the printer history, hence check if
// we need to persist the update.
@@ -433,7 +609,14 @@ public final class FusedPrintersProvider extends Loader> {
if (mHistoricalPrinters.size() >= MAX_HISTORY_LENGTH) {
mHistoricalPrinters.remove(0);
}
- mHistoricalPrinters.add(printer);
+
+ Location location = getCurrentLocation();
+ if (!isLocationAcceptable(location)) {
+ location = null;
+ }
+
+ mHistoricalPrinters.add(new Pair(printer, location));
+
writePrinterHistory();
}
@@ -441,7 +624,7 @@ public final class FusedPrintersProvider extends Loader> {
boolean writeHistory = false;
final int printerCount = mHistoricalPrinters.size();
for (int i = printerCount - 1; i >= 0; i--) {
- PrinterInfo historicalPrinter = mHistoricalPrinters.get(i);
+ PrinterInfo historicalPrinter = mHistoricalPrinters.get(i).first;
if (historicalPrinter.getId().equals(printerId)) {
mHistoricalPrinters.remove(i);
writeHistory = true;
@@ -462,63 +645,91 @@ public final class FusedPrintersProvider extends Loader> {
return mLastReadHistoryTimestamp != mStatePersistFile.getBaseFile().lastModified();
}
- private List computeFavoritePrinters(List printers) {
+ /**
+ * Sort the favorite printers by weight. If a printer is in the list multiple times for
+ * different locations, all instances are considered to have the accumulative weight. The
+ * actual favorite printers to display are computed in {@link #computeAndDeliverResult} as
+ * only at this time we know the location to use to determine if a printer is close enough
+ * to be preferred.
+ *
+ * @param printers The printers to sort.
+ * @return The sorted printers.
+ */
+ private List> sortFavoritePrinters(
+ List> printers) {
Map recordMap = new ArrayMap<>();
- // Recompute the weights.
+ // Compute the weights.
float currentWeight = 1.0f;
final int printerCount = printers.size();
for (int i = printerCount - 1; i >= 0; i--) {
- PrinterInfo printer = printers.get(i);
- // Aggregate weight for the same printer
- PrinterRecord record = recordMap.get(printer.getId());
+ PrinterId printerId = printers.get(i).first.getId();
+ PrinterRecord record = recordMap.get(printerId);
if (record == null) {
- record = new PrinterRecord(printer);
- recordMap.put(printer.getId(), record);
+ record = new PrinterRecord();
+ recordMap.put(printerId, record);
}
+
+ record.printers.add(printers.get(i));
+
+ // Aggregate weight for the same printer
record.weight += currentWeight;
currentWeight *= WEIGHT_DECAY_COEFFICIENT;
}
- // Soft the favorite printers.
+ // Sort the favorite printers.
List favoriteRecords = new ArrayList<>(
recordMap.values());
Collections.sort(favoriteRecords);
// Write the favorites to the output.
- final int favoriteCount = Math.min(favoriteRecords.size(),
- MAX_FAVORITE_PRINTER_COUNT);
- List favoritePrinters = new ArrayList<>(favoriteCount);
- for (int i = 0; i < favoriteCount; i++) {
- PrinterInfo printer = favoriteRecords.get(i).printer;
- favoritePrinters.add(printer);
+ final int recordCount = favoriteRecords.size();
+ List> favoritePrinters = new ArrayList<>(printerCount);
+ for (int i = 0; i < recordCount; i++) {
+ favoritePrinters.addAll(favoriteRecords.get(i).printers);
}
return favoritePrinters;
}
+ /**
+ * A set of printers with the same ID and the weight associated with them during
+ * {@link #sortFavoritePrinters}.
+ */
private final class PrinterRecord implements Comparable {
- public final PrinterInfo printer;
+ /**
+ * The printers, all with the same ID, but potentially different properties or locations
+ */
+ public final List> printers;
+
+ /** The weight associated with the printers */
public float weight;
- public PrinterRecord(PrinterInfo printer) {
- this.printer = printer;
+ /**
+ * Create a new record.
+ */
+ public PrinterRecord() {
+ printers = new ArrayList<>();
}
+ /**
+ * Compare two records by weight.
+ */
@Override
public int compareTo(PrinterRecord another) {
return Float.floatToIntBits(another.weight) - Float.floatToIntBits(weight);
}
}
- private final class ReadTask extends AsyncTask> {
+ private final class ReadTask
+ extends AsyncTask>> {
@Override
- protected List doInBackground(Void... args) {
+ protected List> doInBackground(Void... args) {
return doReadPrinterHistory();
}
@Override
- protected void onPostExecute(List printers) {
+ protected void onPostExecute(List> printers) {
if (DEBUG) {
Log.i(LOG_TAG, "read history completed "
+ FusedPrintersProvider.this.hashCode());
@@ -541,7 +752,8 @@ public final class FusedPrintersProvider extends Loader> {
final int printerCount = printers.size();
for (int i = printerCount - 1; i >= 0; i--) {
- ComponentName printerServiceName = printers.get(i).getId().getServiceName();
+ ComponentName printerServiceName = printers.get(i).first.getId()
+ .getServiceName();
if (!enabledComponents.contains(printerServiceName)) {
printers.remove(i);
}
@@ -552,12 +764,13 @@ public final class FusedPrintersProvider extends Loader> {
// Compute the favorite printers.
mFavoritePrinters.clear();
- mFavoritePrinters.addAll(computeFavoritePrinters(mHistoricalPrinters));
+ mFavoritePrinters.addAll(sortFavoritePrinters(mHistoricalPrinters));
mReadHistoryCompleted = true;
// Deliver the printers.
- updatePrinters(mDiscoverySession.getPrinters(), mFavoritePrinters);
+ updatePrinters(mDiscoverySession.getPrinters(), mFavoritePrinters,
+ getCurrentLocation());
// We are done.
mReadTask = null;
@@ -567,12 +780,12 @@ public final class FusedPrintersProvider extends Loader> {
}
@Override
- protected void onCancelled(List printerInfos) {
+ protected void onCancelled(List> printerInfos) {
// We are done.
mReadTask = null;
}
- private List doReadPrinterHistory() {
+ private List> doReadPrinterHistory() {
final FileInputStream in;
try {
in = mStatePersistFile.openRead();
@@ -584,7 +797,7 @@ public final class FusedPrintersProvider extends Loader> {
return new ArrayList<>();
}
try {
- List printers = new ArrayList<>();
+ List> printers = new ArrayList<>();
XmlPullParser parser = Xml.newPullParser();
parser.setInput(in, StandardCharsets.UTF_8.name());
parseState(parser, printers);
@@ -605,8 +818,9 @@ public final class FusedPrintersProvider extends Loader> {
return Collections.emptyList();
}
- private void parseState(XmlPullParser parser, List outPrinters)
- throws IOException, XmlPullParserException {
+ private void parseState(XmlPullParser parser,
+ List> outPrinters)
+ throws IOException, XmlPullParserException {
parser.next();
skipEmptyTextTags(parser);
expect(parser, XmlPullParser.START_TAG, TAG_PRINTERS);
@@ -624,8 +838,9 @@ public final class FusedPrintersProvider extends Loader> {
expect(parser, XmlPullParser.END_TAG, TAG_PRINTERS);
}
- private boolean parsePrinter(XmlPullParser parser, List outPrinters)
- throws IOException, XmlPullParserException {
+ private boolean parsePrinter(XmlPullParser parser,
+ List> outPrinters)
+ throws IOException, XmlPullParserException {
skipEmptyTextTags(parser);
if (!accept(parser, XmlPullParser.START_TAG, TAG_PRINTER)) {
return false;
@@ -647,6 +862,25 @@ public final class FusedPrintersProvider extends Loader> {
expect(parser, XmlPullParser.END_TAG, TAG_PRINTER_ID);
parser.next();
+ skipEmptyTextTags(parser);
+ Location location;
+ if (accept(parser, XmlPullParser.START_TAG, TAG_LOCATION)) {
+ location = new Location("");
+ location.setLongitude(
+ Double.parseDouble(parser.getAttributeValue(null, ATTR_LONGITUDE)));
+ location.setLatitude(
+ Double.parseDouble(parser.getAttributeValue(null, ATTR_LATITUDE)));
+ location.setAccuracy(
+ Float.parseFloat(parser.getAttributeValue(null, ATTR_ACCURACY)));
+ parser.next();
+
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.END_TAG, TAG_LOCATION);
+ parser.next();
+ } else {
+ location = null;
+ }
+
// If the printer is available the printer will be replaced by the one read from the
// discovery session, hence the only time when this object is used is when the
// printer is unavailable.
@@ -655,7 +889,7 @@ public final class FusedPrintersProvider extends Loader> {
builder.setDescription(description);
PrinterInfo printer = builder.build();
- outPrinters.add(printer);
+ outPrinters.add(new Pair(printer, location));
if (DEBUG) {
Log.i(LOG_TAG, "[RESTORED] " + printer);
@@ -700,15 +934,16 @@ public final class FusedPrintersProvider extends Loader> {
}
}
- private final class WriteTask extends AsyncTask, Void, Void> {
+ private final class WriteTask
+ extends AsyncTask>, Void, Void> {
@Override
protected Void doInBackground(
- @SuppressWarnings("unchecked") List... printers) {
+ @SuppressWarnings("unchecked") List>... printers) {
doWritePrinterHistory(printers[0]);
return null;
}
- private void doWritePrinterHistory(List printers) {
+ private void doWritePrinterHistory(List> printers) {
FileOutputStream out = null;
try {
out = mStatePersistFile.startWrite();
@@ -720,7 +955,7 @@ public final class FusedPrintersProvider extends Loader> {
final int printerCount = printers.size();
for (int i = 0; i < printerCount; i++) {
- PrinterInfo printer = printers.get(i);
+ PrinterInfo printer = printers.get(i).first;
serializer.startTag(null, TAG_PRINTER);
@@ -737,6 +972,18 @@ public final class FusedPrintersProvider extends Loader> {
.flattenToString());
serializer.endTag(null, TAG_PRINTER_ID);
+ Location location = printers.get(i).second;
+ if (location != null) {
+ serializer.startTag(null, TAG_LOCATION);
+ serializer.attribute(null, ATTR_LONGITUDE,
+ String.valueOf(location.getLongitude()));
+ serializer.attribute(null, ATTR_LATITUDE,
+ String.valueOf(location.getLatitude()));
+ serializer.attribute(null, ATTR_ACCURACY,
+ String.valueOf(location.getAccuracy()));
+ serializer.endTag(null, TAG_LOCATION);
+ }
+
serializer.endTag(null, TAG_PRINTER);
if (DEBUG) {
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index f604bb781452b..b254f29e0d5a3 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -594,6 +594,14 @@ final class DefaultPermissionGrantPolicy {
}
}
+ // Print Spooler
+ PackageParser.Package printSpoolerPackage = getSystemPackageLPr(
+ "com.android.printspooler");
+ if (printSpoolerPackage != null
+ && doesPackageSupportRuntimePermissions(printSpoolerPackage)) {
+ grantRuntimePermissionsLPw(printSpoolerPackage, LOCATION_PERMISSIONS, true, userId);
+ }
+
mService.mSettings.onDefaultRuntimePermissionsGrantedLPr(userId);
}
}