From c0a128dc2b3e7af35cb39d5157ca4de9147aa3c8 Mon Sep 17 00:00:00 2001
From: "Philip P. Moltmann"
This can be used for dumping {@link android.util.proto.ProtoOutputStream protos}.
+ *
+ * @param binder The service providing the data
+ * @param args The arguments passed to the dump function of the service
+ */
+ public static byte[] dumpAsync(@NonNull IBinder binder, @Nullable String... args)
+ throws IOException, RemoteException {
+ ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
+ try {
+ TransferPipe.dumpAsync(binder, pipe[1].getFileDescriptor(), args);
+
+ // Data is written completely when dumpAsync is done
+ pipe[1].close();
+ pipe[1] = null;
+
+ byte[] buffer = new byte[4096];
+ try (ByteArrayOutputStream combinedBuffer = new ByteArrayOutputStream()) {
+ try (FileInputStream is = new FileInputStream(pipe[0].getFileDescriptor())) {
+ while (true) {
+ int numRead = is.read(buffer);
+ if (numRead == -1) {
+ break;
+ }
+
+ combinedBuffer.write(buffer, 0, numRead);
+ }
+ }
+
+ return combinedBuffer.toByteArray();
+ }
+ } finally {
+ pipe[0].close();
+ IoUtils.closeQuietly(pipe[1]);
+ }
+ }
+
static void go(Caller caller, IInterface iface, FileDescriptor out,
String prefix, String[] args) throws IOException, RemoteException {
go(caller, iface, out, prefix, args, DEFAULT_TIMEOUT);
diff --git a/core/java/com/android/internal/print/DumpUtils.java b/core/java/com/android/internal/print/DumpUtils.java
new file mode 100644
index 0000000000000..28c7fc2182b29
--- /dev/null
+++ b/core/java/com/android/internal/print/DumpUtils.java
@@ -0,0 +1,356 @@
+/*
+ * Copyright (C) 2017 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.internal.print;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.ComponentNameProto;
+import android.content.Context;
+import android.print.PageRange;
+import android.print.PrintAttributes;
+import android.print.PrintDocumentInfo;
+import android.print.PrintJobId;
+import android.print.PrintJobInfo;
+import android.print.PrinterCapabilitiesInfo;
+import android.print.PrinterId;
+import android.print.PrinterInfo;
+import android.service.print.MarginsProto;
+import android.service.print.MediaSizeProto;
+import android.service.print.PageRangeProto;
+import android.service.print.PrintAttributesProto;
+import android.service.print.PrintDocumentInfoProto;
+import android.service.print.PrintJobInfoProto;
+import android.service.print.PrinterCapabilitiesProto;
+import android.service.print.PrinterIdProto;
+import android.service.print.PrinterInfoProto;
+import android.service.print.ResolutionProto;
+import android.util.proto.ProtoOutputStream;
+
+/**
+ * Utilities for dumping print related proto buffer
+ */
+public class DumpUtils {
+ /**
+ * Write a string to a proto if the string is not {@code null}.
+ *
+ * @param proto The proto to write to
+ * @param id The proto-id of the string
+ * @param string The string to write
+ */
+ public static void writeStringIfNotNull(@NonNull ProtoOutputStream proto, long id,
+ @Nullable String string) {
+ if (string != null) {
+ proto.write(id, string);
+ }
+ }
+
+ /**
+ * Write a {@link ComponentName} to a proto.
+ *
+ * @param proto The proto to write to
+ * @param id The proto-id of the component name
+ * @param component The component name to write
+ */
+ public static void writeComponentName(@NonNull ProtoOutputStream proto, long id,
+ @NonNull ComponentName component) {
+ long token = proto.start(id);
+ proto.write(ComponentNameProto.PACKAGE_NAME, component.getPackageName());
+ proto.write(ComponentNameProto.CLASS_NAME, component.getClassName());
+ proto.end(token);
+ }
+
+ /**
+ * Write a {@link PrinterId} to a proto.
+ *
+ * @param proto The proto to write to
+ * @param id The proto-id of the component name
+ * @param printerId The printer id to write
+ */
+ public static void writePrinterId(@NonNull ProtoOutputStream proto, long id,
+ @NonNull PrinterId printerId) {
+ long token = proto.start(id);
+ writeComponentName(proto, PrinterIdProto.SERVICE_NAME, printerId.getServiceName());
+ proto.write(PrinterIdProto.LOCAL_ID, printerId.getLocalId());
+ proto.end(token);
+ }
+
+ /**
+ * Write a {@link PrinterCapabilitiesInfo} to a proto.
+ *
+ * @param proto The proto to write to
+ * @param id The proto-id of the component name
+ * @param cap The capabilities to write
+ */
+ public static void writePrinterCapabilities(@NonNull Context context,
+ @NonNull ProtoOutputStream proto, long id, @NonNull PrinterCapabilitiesInfo cap) {
+ long token = proto.start(id);
+ writeMargins(proto, PrinterCapabilitiesProto.MIN_MARGINS, cap.getMinMargins());
+
+ int numMediaSizes = cap.getMediaSizes().size();
+ for (int i = 0; i < numMediaSizes; i++) {
+ writeMediaSize(context, proto, PrinterCapabilitiesProto.MEDIA_SIZES,
+ cap.getMediaSizes().get(i));
+ }
+
+ int numResolutions = cap.getResolutions().size();
+ for (int i = 0; i < numResolutions; i++) {
+ writeResolution(proto, PrinterCapabilitiesProto.RESOLUTIONS,
+ cap.getResolutions().get(i));
+ }
+
+ if ((cap.getColorModes() & PrintAttributes.COLOR_MODE_MONOCHROME) != 0) {
+ proto.write(PrinterCapabilitiesProto.COLOR_MODES,
+ PrintAttributesProto.COLOR_MODE_MONOCHROME);
+ }
+ if ((cap.getColorModes() & PrintAttributes.COLOR_MODE_COLOR) != 0) {
+ proto.write(PrinterCapabilitiesProto.COLOR_MODES,
+ PrintAttributesProto.COLOR_MODE_COLOR);
+ }
+
+ if ((cap.getDuplexModes() & PrintAttributes.DUPLEX_MODE_NONE) != 0) {
+ proto.write(PrinterCapabilitiesProto.DUPLEX_MODES,
+ PrintAttributesProto.DUPLEX_MODE_NONE);
+ }
+ if ((cap.getDuplexModes() & PrintAttributes.DUPLEX_MODE_LONG_EDGE) != 0) {
+ proto.write(PrinterCapabilitiesProto.DUPLEX_MODES,
+ PrintAttributesProto.DUPLEX_MODE_LONG_EDGE);
+ }
+ if ((cap.getDuplexModes() & PrintAttributes.DUPLEX_MODE_SHORT_EDGE) != 0) {
+ proto.write(PrinterCapabilitiesProto.DUPLEX_MODES,
+ PrintAttributesProto.DUPLEX_MODE_SHORT_EDGE);
+ }
+
+ proto.end(token);
+ }
+
+
+ /**
+ * Write a {@link PrinterInfo} to a proto.
+ *
+ * @param context The context used to resolve resources
+ * @param proto The proto to write to
+ * @param id The proto-id of the component name
+ * @param info The printer info to write
+ */
+ public static void writePrinterInfo(@NonNull Context context, @NonNull ProtoOutputStream proto,
+ long id, @NonNull PrinterInfo info) {
+ long token = proto.start(id);
+ writePrinterId(proto, PrinterInfoProto.ID, info.getId());
+ proto.write(PrinterInfoProto.NAME, info.getName());
+ proto.write(PrinterInfoProto.STATUS, info.getStatus());
+ proto.write(PrinterInfoProto.DESCRIPTION, info.getDescription());
+
+ PrinterCapabilitiesInfo cap = info.getCapabilities();
+ if (cap != null) {
+ writePrinterCapabilities(context, proto, PrinterInfoProto.CAPABILITIES, cap);
+ }
+
+ proto.end(token);
+ }
+
+ /**
+ * Write a {@link PrintAttributes.MediaSize} to a proto.
+ *
+ * @param context The context used to resolve resources
+ * @param proto The proto to write to
+ * @param id The proto-id of the component name
+ * @param mediaSize The media size to write
+ */
+ public static void writeMediaSize(@NonNull Context context, @NonNull ProtoOutputStream proto,
+ long id, @NonNull PrintAttributes.MediaSize mediaSize) {
+ long token = proto.start(id);
+ proto.write(MediaSizeProto.ID, mediaSize.getId());
+ proto.write(MediaSizeProto.LABEL, mediaSize.getLabel(context.getPackageManager()));
+ proto.write(MediaSizeProto.HEIGHT_MILS, mediaSize.getHeightMils());
+ proto.write(MediaSizeProto.WIDTH_MILS, mediaSize.getWidthMils());
+ proto.end(token);
+ }
+
+ /**
+ * Write a {@link PrintAttributes.Resolution} to a proto.
+ *
+ * @param proto The proto to write to
+ * @param id The proto-id of the component name
+ * @param res The resolution to write
+ */
+ public static void writeResolution(@NonNull ProtoOutputStream proto, long id,
+ @NonNull PrintAttributes.Resolution res) {
+ long token = proto.start(id);
+ proto.write(ResolutionProto.ID, res.getId());
+ proto.write(ResolutionProto.LABEL, res.getLabel());
+ proto.write(ResolutionProto.HORIZONTAL_DPI, res.getHorizontalDpi());
+ proto.write(ResolutionProto.VERTICAL_DPI, res.getVerticalDpi());
+ proto.end(token);
+ }
+
+ /**
+ * Write a {@link PrintAttributes.Margins} to a proto.
+ *
+ * @param proto The proto to write to
+ * @param id The proto-id of the component name
+ * @param margins The margins to write
+ */
+ public static void writeMargins(@NonNull ProtoOutputStream proto, long id,
+ @NonNull PrintAttributes.Margins margins) {
+ long token = proto.start(id);
+ proto.write(MarginsProto.TOP_MILS, margins.getTopMils());
+ proto.write(MarginsProto.LEFT_MILS, margins.getLeftMils());
+ proto.write(MarginsProto.RIGHT_MILS, margins.getRightMils());
+ proto.write(MarginsProto.BOTTOM_MILS, margins.getBottomMils());
+ proto.end(token);
+ }
+
+ /**
+ * Write a {@link PrintAttributes} to a proto.
+ *
+ * @param context The context used to resolve resources
+ * @param proto The proto to write to
+ * @param id The proto-id of the component name
+ * @param attributes The attributes to write
+ */
+ public static void writePrintAttributes(@NonNull Context context,
+ @NonNull ProtoOutputStream proto, long id, @NonNull PrintAttributes attributes) {
+ long token = proto.start(id);
+
+ PrintAttributes.MediaSize mediaSize = attributes.getMediaSize();
+ if (mediaSize != null) {
+ writeMediaSize(context, proto, PrintAttributesProto.MEDIA_SIZE, mediaSize);
+ }
+
+ proto.write(PrintAttributesProto.IS_PORTRAIT, attributes.isPortrait());
+
+ PrintAttributes.Resolution res = attributes.getResolution();
+ if (res != null) {
+ writeResolution(proto, PrintAttributesProto.RESOLUTION, res);
+ }
+
+ PrintAttributes.Margins minMargins = attributes.getMinMargins();
+ if (minMargins != null) {
+ writeMargins(proto, PrintAttributesProto.MIN_MARGINS, minMargins);
+ }
+
+ proto.write(PrintAttributesProto.COLOR_MODE, attributes.getColorMode());
+ proto.write(PrintAttributesProto.DUPLEX_MODE, attributes.getDuplexMode());
+ proto.end(token);
+ }
+
+ /**
+ * Write a {@link PrintDocumentInfo} to a proto.
+ *
+ * @param proto The proto to write to
+ * @param id The proto-id of the component name
+ * @param info The info to write
+ */
+ public static void writePrintDocumentInfo(@NonNull ProtoOutputStream proto, long id,
+ @NonNull PrintDocumentInfo info) {
+ long token = proto.start(id);
+ proto.write(PrintDocumentInfoProto.NAME, info.getName());
+
+ int pageCount = info.getPageCount();
+ if (pageCount != PrintDocumentInfo.PAGE_COUNT_UNKNOWN) {
+ proto.write(PrintDocumentInfoProto.PAGE_COUNT, pageCount);
+ }
+
+ proto.write(PrintDocumentInfoProto.CONTENT_TYPE, info.getContentType());
+ proto.write(PrintDocumentInfoProto.DATA_SIZE, info.getDataSize());
+ proto.end(token);
+ }
+
+ /**
+ * Write a {@link PageRange} to a proto.
+ *
+ * @param proto The proto to write to
+ * @param id The proto-id of the component name
+ * @param range The range to write
+ */
+ public static void writePageRange(@NonNull ProtoOutputStream proto, long id,
+ @NonNull PageRange range) {
+ long token = proto.start(id);
+ proto.write(PageRangeProto.START, range.getStart());
+ proto.write(PageRangeProto.END, range.getEnd());
+ proto.end(token);
+ }
+
+ /**
+ * Write a {@link PrintJobInfo} to a proto.
+ *
+ * @param context The context used to resolve resources
+ * @param proto The proto to write to
+ * @param id The proto-id of the component name
+ * @param printJobInfo The print job info to write
+ */
+ public static void writePrintJobInfo(@NonNull Context context, @NonNull ProtoOutputStream proto,
+ long id, @NonNull PrintJobInfo printJobInfo) {
+ long token = proto.start(id);
+ proto.write(PrintJobInfoProto.LABEL, printJobInfo.getLabel());
+
+ PrintJobId printJobId = printJobInfo.getId();
+ if (printJobId != null) {
+ proto.write(PrintJobInfoProto.PRINT_JOB_ID, printJobId.flattenToString());
+ }
+
+ int state = printJobInfo.getState();
+ if (state >= PrintJobInfoProto.STATE_CREATED && state <= PrintJobInfoProto.STATE_CANCELED) {
+ proto.write(PrintJobInfoProto.STATE, state);
+ } else {
+ proto.write(PrintJobInfoProto.STATE, PrintJobInfoProto.STATE_UNKNOWN);
+ }
+
+ PrinterId printer = printJobInfo.getPrinterId();
+ if (printer != null) {
+ writePrinterId(proto, PrintJobInfoProto.PRINTER, printer);
+ }
+
+ String tag = printJobInfo.getTag();
+ if (tag != null) {
+ proto.write(PrintJobInfoProto.TAG, tag);
+ }
+
+ proto.write(PrintJobInfoProto.CREATION_TIME, printJobInfo.getCreationTime());
+
+ PrintAttributes attributes = printJobInfo.getAttributes();
+ if (attributes != null) {
+ writePrintAttributes(context, proto, PrintJobInfoProto.ATTRIBUTES, attributes);
+ }
+
+ PrintDocumentInfo docInfo = printJobInfo.getDocumentInfo();
+ if (docInfo != null) {
+ writePrintDocumentInfo(proto, PrintJobInfoProto.DOCUMENT_INFO, docInfo);
+ }
+
+ proto.write(PrintJobInfoProto.IS_CANCELING, printJobInfo.isCancelling());
+
+ PageRange[] pages = printJobInfo.getPages();
+ if (pages != null) {
+ for (int i = 0; i < pages.length; i++) {
+ writePageRange(proto, PrintJobInfoProto.PAGES, pages[i]);
+ }
+ }
+
+ proto.write(PrintJobInfoProto.HAS_ADVANCED_OPTIONS,
+ printJobInfo.getAdvancedOptions() != null);
+ proto.write(PrintJobInfoProto.PROGRESS, printJobInfo.getProgress());
+
+ CharSequence status = printJobInfo.getStatus(context.getPackageManager());
+ if (status != null) {
+ proto.write(PrintJobInfoProto.STATUS, status.toString());
+ }
+
+ proto.end(token);
+ }
+}
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index e1991146ddb9a..5914f5665eb75 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -28,6 +28,7 @@ import "frameworks/base/core/proto/android/service/netstats.proto";
import "frameworks/base/core/proto/android/service/notification.proto";
import "frameworks/base/core/proto/android/service/package.proto";
import "frameworks/base/core/proto/android/service/power.proto";
+import "frameworks/base/core/proto/android/service/print.proto";
import "frameworks/base/core/proto/android/providers/settings.proto";
import "frameworks/base/core/proto/android/os/kernelwake.proto";
@@ -66,4 +67,5 @@ message IncidentProto {
android.service.notification.NotificationServiceDumpProto notification = 3004;
android.service.pm.PackageServiceDumpProto package = 3008;
android.service.power.PowerServiceDumpProto power = 3009;
+ android.service.print.PrintServiceDumpProto print = 3010;
}
diff --git a/core/proto/android/service/print.proto b/core/proto/android/service/print.proto
new file mode 100644
index 0000000000000..f09987248d58d
--- /dev/null
+++ b/core/proto/android/service/print.proto
@@ -0,0 +1,368 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+syntax = "proto3";
+
+package android.service.print;
+
+option java_multiple_files = true;
+option java_outer_classname = "PrintServiceProto";
+
+import "frameworks/base/core/proto/android/content/component_name.proto";
+
+message PrintServiceDumpProto {
+ // Each user has a separate printer state
+ repeated PrintUserStateProto userStates = 1;
+}
+
+message PrintUserStateProto {
+ // Should be 0, 10, 11, 12, etc. where 0 is the owner.
+ int32 user_id = 1;
+
+ // The installed print services
+ repeated InstalledPrintServiceProto installed_services = 2;
+
+ // The disabled print services
+ repeated android.content.ComponentNameProto disabled_services = 3;
+
+ // The active print services
+ repeated ActivePrintServiceProto active_services = 4;
+
+ // The cached print jobs
+ repeated CachedPrintJobProto cached_print_jobs = 5;
+
+ // The printer discovery sessions
+ repeated PrinterDiscoverySessionProto discovery_sessions = 6;
+
+ // The print spooler state
+ PrintSpoolerStateProto print_spooler_state = 7;
+}
+
+message PrintSpoolerStateProto {
+ // Is the print spooler destroyed?
+ bool is_destroyed = 1;
+
+ // Is the print spooler bound?
+ bool is_bound = 2;
+
+ // State internal to the print spooler
+ PrintSpoolerInternalStateProto internal_state = 3;
+}
+
+message PrintSpoolerInternalStateProto {
+ // Print jobs
+ repeated PrintJobInfoProto print_jobs = 1;
+
+ // Files used by these print jobs
+ repeated string print_job_files = 2;
+
+ // Approved print services
+ repeated android.content.ComponentNameProto approved_services = 3;
+}
+
+message PrinterCapabilitiesProto {
+ // Minimum margins of the printer
+ MarginsProto min_margins = 1;
+
+ // List of supported media sizes
+ repeated MediaSizeProto media_sizes = 2;
+
+ // List of supported resolutions
+ repeated ResolutionProto resolutions = 3;
+
+ // List of supported color modes
+ repeated PrintAttributesProto.ColorMode color_modes = 4;
+
+ // List of supported duplex modes
+ repeated PrintAttributesProto.DuplexMode duplex_modes = 5;
+}
+
+message PrinterInfoProto {
+ // The id of the printer
+ PrinterIdProto id = 1;
+
+ // The name of the printer
+ string name = 2;
+
+ enum Status {
+ // unused
+ __STATUS_UNUSED = 0;
+
+ // Printer is idle
+ STATUS_IDLE = 1;
+
+ // Printer is busy
+ STATUS_BUSY = 2;
+
+ // Printer is unavailable
+ STATUS_UNAVAILABLE = 3;
+ }
+ // The status of the printer
+ Status status = 3;
+
+ // The description of the printer
+ string description = 4;
+
+ // The capabilities of the printer
+ PrinterCapabilitiesProto capabilities = 5;
+}
+
+message PrinterDiscoverySessionProto {
+ // Is this session destroyed?
+ bool is_destroyed = 1;
+
+ // Is printer discovery in progress?
+ bool is_printer_discovery_in_progress = 2;
+
+ // List of printer discovery observers
+ repeated string printer_discovery_observers = 3;
+
+ // List of discovery request
+ repeated string discovery_requests = 4;
+
+ // List of ids of printers that are have tracking requests
+ repeated PrinterIdProto tracked_printer_requests = 5;
+
+ // List of printers found
+ repeated PrinterInfoProto printer = 6;
+}
+
+message InstalledPrintServiceProto {
+ // Component name of the service
+ android.content.ComponentNameProto component_name = 1;
+
+ // Settings activity for this service
+ string settings_activity = 2;
+
+ // Add printers activity for this service
+ string add_printers_activity = 3;
+
+ // Advances options activity for this service
+ string advanced_options_activity = 4;
+}
+
+message PrinterIdProto {
+ // Component name of the service that reported the printer
+ android.content.ComponentNameProto service_name = 1;
+
+ // Local id of the printer
+ string local_id = 2;
+}
+
+message ActivePrintServiceProto {
+ // Component name of the service
+ android.content.ComponentNameProto component_name = 1;
+
+ // Is the active service destroyed
+ bool is_destroyed = 2;
+
+ // Is the active service bound
+ bool is_bound = 3;
+
+ // Has the active service a discovery session
+ bool has_discovery_session = 4;
+
+ // Has the active service a active print jobs
+ bool has_active_print_jobs = 5;
+
+ // Is the active service discovering printers
+ bool is_discovering_printers = 6;
+
+ // The tracked printers of this active service
+ repeated PrinterIdProto tracked_printers = 7;
+}
+
+message MediaSizeProto {
+ // Id of this media size
+ string id = 1;
+
+ // Label of this media size
+ string label = 2;
+
+ // Height of the media
+ int32 height_mils = 3;
+
+ // Width of the media
+ int32 width_mils = 4;
+}
+
+message ResolutionProto {
+ // Id of this resolution
+ string id = 1;
+
+ // Label for this resoltion
+ string label = 2;
+
+ // Resolution in horizontal orientation
+ int32 horizontal_dpi = 3;
+
+ // Resolution in vertical orientation
+ int32 vertical_dpi = 4;
+}
+
+message MarginsProto {
+ // Space at the top
+ int32 top_mils = 1;
+
+ // Space at the left
+ int32 left_mils = 2;
+
+ // Space at the right
+ int32 right_mils = 3;
+
+ // Space at the bottom
+ int32 bottom_mils = 4;
+}
+
+message PrintAttributesProto {
+ // Media to use
+ ResolutionProto media_size = 1;
+
+ // Is the media in portrait mode?
+ bool is_portrait = 2;
+
+ // Resolution to use
+ ResolutionProto resolution = 3;
+
+ // Margins around the document
+ MarginsProto min_margins = 4;
+
+ enum ColorMode {
+ // unused
+ __COLOR_MODE_UNUSED = 0;
+
+ // Use black, white, gray
+ COLOR_MODE_MONOCHROME = 1;
+
+ // Use full color is available
+ COLOR_MODE_COLOR = 2;
+ }
+ // Color mode to use
+ ColorMode color_mode = 5;
+
+ enum DuplexMode {
+ // unused
+ __DUPLEX_MODE_UNUSED = 0;
+
+ // No duplex
+ DUPLEX_MODE_NONE = 1;
+
+ // Duplex where the long edge attached
+ DUPLEX_MODE_LONG_EDGE = 2;
+
+ // Duplex where the short edge attach
+ DUPLEX_MODE_SHORT_EDGE = 4;
+ }
+ // Duplex mode to use
+ DuplexMode duplex_mode = 6;
+}
+
+message PrintDocumentInfoProto {
+ // Name of the document to print
+ string name = 1;
+
+ // Number of pages in the doc
+ int32 page_count = 2;
+
+ // Type of content (see PrintDocumentInfo.ContentType)
+ int32 content_type = 3;
+
+ // The size of the the document
+ int64 data_size = 4;
+}
+
+message PageRangeProto {
+ // Start of the range
+ int32 start = 1;
+
+ // End of the range (included)
+ int32 end = 2;
+}
+
+message PrintJobInfoProto {
+ // Label of the job
+ string label = 1;
+
+ // Id of the job
+ string print_job_id = 2;
+
+ enum State {
+ // Unknown state
+ STATE_UNKNOWN = 0;
+
+ // The print job is being created but not yet ready to be printed
+ STATE_CREATED = 1;
+
+ // The print jobs is created, it is ready to be printed and should be processed
+ STATE_QUEUED = 2;
+
+ // The print job is being printed
+ STATE_STARTED = 3;
+
+ // The print job is blocked
+ STATE_BLOCKED = 4;
+
+ // The print job is successfully printed
+ STATE_COMPLETED = 5;
+
+ // The print job was printing but printing failed
+ STATE_FAILED = 6;
+
+ // The print job is canceled
+ STATE_CANCELED = 7;
+ }
+
+ // State of the job
+ State state = 3;
+
+ // Printer handling the job
+ PrinterIdProto printer = 4;
+
+ // Tag assigned to the job
+ string tag = 5;
+
+ // Time the job was created
+ int64 creation_time = 6;
+
+ // Attributes of the job
+ PrintAttributesProto attributes = 7;
+
+ // Document info of the job
+ PrintDocumentInfoProto document_info = 8;
+
+ // If the job current getting canceled
+ bool is_canceling = 9;
+
+ // The selected ranges of the job
+ repeated PageRangeProto pages = 10;
+
+ // Does the job have any advanced options
+ bool has_advanced_options = 11;
+
+ // Progress of the job
+ float progress = 12;
+
+ // The current service set state
+ string status = 13;
+}
+
+message CachedPrintJobProto {
+ // The id of the app the job belongs to
+ int32 app_id = 1;
+
+ // The print job
+ PrintJobInfoProto print_job = 2;
+}
\ No newline at end of file
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java b/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java
index d15ae1c07ca77..e0a3f6cb31cac 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java
@@ -16,6 +16,9 @@
package com.android.printspooler.model;
+import static com.android.internal.print.DumpUtils.writeComponentName;
+import static com.android.internal.print.DumpUtils.writePrintJobInfo;
+
import android.annotation.FloatRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -26,6 +29,7 @@ import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Icon;
import android.os.AsyncTask;
+import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Message;
@@ -44,16 +48,19 @@ import android.print.PrintJobId;
import android.print.PrintJobInfo;
import android.print.PrintManager;
import android.print.PrinterId;
+import android.service.print.PrintSpoolerInternalStateProto;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.AtomicFile;
import android.util.Log;
import android.util.Slog;
import android.util.Xml;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.os.HandlerCaller;
import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.Preconditions;
import com.android.printspooler.R;
import com.android.printspooler.util.ApprovedPrintServices;
@@ -152,29 +159,26 @@ public final class PrintSpoolerService extends Service {
return new PrintSpooler();
}
- @Override
- protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ private void dumpLocked(PrintWriter pw, String[] args) {
String prefix = (args.length > 0) ? args[0] : "";
String tab = " ";
- synchronized (mLock) {
- pw.append(prefix).append("print jobs:").println();
- final int printJobCount = mPrintJobs.size();
- for (int i = 0; i < printJobCount; i++) {
- PrintJobInfo printJob = mPrintJobs.get(i);
- pw.append(prefix).append(tab).append(printJob.toString());
- pw.println();
- }
+ pw.append(prefix).append("print jobs:").println();
+ final int printJobCount = mPrintJobs.size();
+ for (int i = 0; i < printJobCount; i++) {
+ PrintJobInfo printJob = mPrintJobs.get(i);
+ pw.append(prefix).append(tab).append(printJob.toString());
+ pw.println();
+ }
- pw.append(prefix).append("print job files:").println();
- File[] files = getFilesDir().listFiles();
- if (files != null) {
- final int fileCount = files.length;
- for (int i = 0; i < fileCount; i++) {
- File file = files[i];
- if (file.isFile() && file.getName().startsWith(PRINT_JOB_FILE_PREFIX)) {
- pw.append(prefix).append(tab).append(file.getName()).println();
- }
+ pw.append(prefix).append("print job files:").println();
+ File[] files = getFilesDir().listFiles();
+ if (files != null) {
+ final int fileCount = files.length;
+ for (int i = 0; i < fileCount; i++) {
+ File file = files[i];
+ if (file.isFile() && file.getName().startsWith(PRINT_JOB_FILE_PREFIX)) {
+ pw.append(prefix).append(tab).append(file.getName()).println();
}
}
}
@@ -188,6 +192,68 @@ public final class PrintSpoolerService extends Service {
}
}
+ private void dumpLocked(@NonNull ProtoOutputStream proto) {
+ int numPrintJobs = mPrintJobs.size();
+ for (int i = 0; i < numPrintJobs; i++) {
+ writePrintJobInfo(this, proto, PrintSpoolerInternalStateProto.PRINT_JOBS,
+ mPrintJobs.get(i));
+ }
+
+ File[] files = getFilesDir().listFiles();
+ if (files != null) {
+ for (int i = 0; i < files.length; i++) {
+ File file = files[i];
+ if (file.isFile() && file.getName().startsWith(PRINT_JOB_FILE_PREFIX)) {
+ proto.write(PrintSpoolerInternalStateProto.PRINT_JOB_FILES, file.getName());
+ }
+ }
+ }
+
+ Set