Merge "Add dumping the state of the print sub-system." into klp-dev
diff --git a/core/java/android/printservice/PrintService.java b/core/java/android/printservice/PrintService.java
index 96552af..0ffc40a 100644
--- a/core/java/android/printservice/PrintService.java
+++ b/core/java/android/printservice/PrintService.java
@@ -20,6 +20,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -155,6 +156,8 @@
 
     private static final String LOG_TAG = "PrintService";
 
+    private static final boolean DEBUG = false;
+
     /**
      * The {@link Intent} action that must be declared as handled by a service
      * in its manifest for the system to recognize it as a print service.
@@ -433,6 +436,9 @@
 
                 case MSG_ON_PRINTJOB_QUEUED: {
                     PrintJobInfo printJobInfo = (PrintJobInfo) message.obj;
+                    if (DEBUG) {
+                        Log.i(LOG_TAG, "Queued: " + printJobInfo);
+                    }
                     onPrintJobQueued(new PrintJob(printJobInfo, mClient));
                 } break;
 
diff --git a/core/java/android/printservice/PrintServiceInfo.java b/core/java/android/printservice/PrintServiceInfo.java
index 128628d..8e9636c 100644
--- a/core/java/android/printservice/PrintServiceInfo.java
+++ b/core/java/android/printservice/PrintServiceInfo.java
@@ -239,10 +239,10 @@
     public String toString() {
         StringBuilder builder = new StringBuilder();
         builder.append("PrintServiceInfo{");
-        builder.append("id:").append(mId).append(", ");
-        builder.append("resolveInfo:").append(mResolveInfo).append(", ");
-        builder.append("settingsActivityName:").append(mSettingsActivityName);
-        builder.append("addPrintersActivityName:").append(mAddPrintersActivityName);
+        builder.append("id=").append(mId);
+        builder.append(", resolveInfo=").append(mResolveInfo);
+        builder.append(", settingsActivityName=").append(mSettingsActivityName);
+        builder.append(", addPrintersActivityName=").append(mAddPrintersActivityName);
         builder.append("}");
         return builder.toString();
     }
diff --git a/services/java/com/android/server/print/PrintManagerService.java b/services/java/com/android/server/print/PrintManagerService.java
index 2563b58..926f822 100644
--- a/services/java/com/android/server/print/PrintManagerService.java
+++ b/services/java/com/android/server/print/PrintManagerService.java
@@ -41,6 +41,8 @@
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.os.BackgroundThread;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
@@ -298,6 +300,27 @@
         }
     }
 
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
+                != PackageManager.PERMISSION_GRANTED) {
+            pw.println("Permission Denial: can't dump PrintManager from from pid="
+                    + Binder.getCallingPid()
+                    + ", uid=" + Binder.getCallingUid());
+            return;
+        }
+
+        synchronized (mLock) {
+            pw.println("PRINT MANAGER STATE (dumpsys print)");
+            final int userStateCount = mUserStates.size();
+            for (int i = 0; i < userStateCount; i++) {
+                UserState userState = mUserStates.get(i);
+                userState.dump(fd, pw, "");
+                pw.println();
+            }
+        }
+    }
+
     private void registerContentObservers() {
         final Uri enabledPrintServicesUri = Settings.Secure.getUriFor(
                 Settings.Secure.ENABLED_PRINT_SERVICES);
diff --git a/services/java/com/android/server/print/RemotePrintService.java b/services/java/com/android/server/print/RemotePrintService.java
index 2ded202..ddff0ae 100644
--- a/services/java/com/android/server/print/RemotePrintService.java
+++ b/services/java/com/android/server/print/RemotePrintService.java
@@ -41,6 +41,7 @@
 
 import com.android.internal.R;
 
+import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.List;
@@ -137,6 +138,19 @@
         }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
     }
 
+    public void dump(PrintWriter pw, String prefix) {
+        String tab = "  ";
+        pw.append(prefix).append("service:").println();
+        pw.append(prefix).append(tab).append("componentName=")
+                .append(mComponentName.flattenToString()).println();
+        pw.append(prefix).append(tab).append("destroyed=")
+                .append(String.valueOf(mDestroyed)).println();
+        pw.append(prefix).append(tab).append("bound=")
+                .append(String.valueOf(isBound())).println();
+        pw.append(prefix).append(tab).append("hasDicoverySession=")
+                .append(String.valueOf(mHasPrinterDiscoverySession));
+    }
+
     private void failAllActivePrintJobs() {
         List<PrintJobInfo> printJobs = mSpooler.getPrintJobInfos(mComponentName,
                 PrintJobInfo.STATE_ANY_ACTIVE, PrintManager.APP_ID_ANY);
diff --git a/services/java/com/android/server/print/RemotePrintSpooler.java b/services/java/com/android/server/print/RemotePrintSpooler.java
index db0eb33..28a6186 100644
--- a/services/java/com/android/server/print/RemotePrintSpooler.java
+++ b/services/java/com/android/server/print/RemotePrintSpooler.java
@@ -34,11 +34,14 @@
 import android.print.IPrintSpoolerClient;
 import android.print.PrintAttributes;
 import android.print.PrintJobInfo;
+import android.print.PrintManager;
 import android.util.Slog;
 import android.util.TimedRemoteCaller;
 
 import libcore.io.IoUtils;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.util.List;
 import java.util.concurrent.TimeoutException;
@@ -291,6 +294,28 @@
         }
     }
 
+    public void dump(FileDescriptor fd, PrintWriter pw, String prefix) {
+        synchronized (mLock) {
+            pw.append(prefix).append("destroyed=")
+                    .append(String.valueOf(mDestroyed)).println();
+            pw.append(prefix).append("bound=")
+                    .append((mRemoteInstance != null) ? "true" : "false").println();
+            pw.append(prefix).append("print jobs:").println();
+            if (mRemoteInstance != null) {
+                List<PrintJobInfo> printJobs = getPrintJobInfos(null,
+                        PrintJobInfo.STATE_ANY, PrintManager.APP_ID_ANY);
+                if (printJobs != null) {
+                    final int printJobCount = printJobs.size();
+                    for (int i = 0; i < printJobCount; i++) {
+                        PrintJobInfo printJob = printJobs.get(i);
+                        pw.append(prefix).append(prefix).append(printJob.toString());
+                        pw.println();
+                    }
+                }
+            }
+        }
+    }
+
     private void onAllPrintJobsHandled() {
         synchronized (mLock) {
             throwIfDestroyedLocked();
diff --git a/services/java/com/android/server/print/UserState.java b/services/java/com/android/server/print/UserState.java
index b37a0d9..5392975 100644
--- a/services/java/com/android/server/print/UserState.java
+++ b/services/java/com/android/server/print/UserState.java
@@ -39,14 +39,16 @@
 import android.text.TextUtils;
 import android.text.TextUtils.SimpleStringSplitter;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.Log;
 import android.util.Slog;
 
 import com.android.internal.os.SomeArgs;
 import com.android.server.print.RemotePrintSpooler.PrintSpoolerCallbacks;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
@@ -72,14 +74,14 @@
     private final Intent mQueryIntent =
             new Intent(android.printservice.PrintService.SERVICE_INTERFACE);
 
-    private final Map<ComponentName, RemotePrintService> mActiveServices =
-            new HashMap<ComponentName, RemotePrintService>();
+    private final ArrayMap<ComponentName, RemotePrintService> mActiveServices =
+            new ArrayMap<ComponentName, RemotePrintService>();
 
     private final List<PrintServiceInfo> mInstalledServices =
             new ArrayList<PrintServiceInfo>();
 
     private final Set<ComponentName> mEnabledServices =
-            new HashSet<ComponentName>();
+            new ArraySet<ComponentName>();
 
     private final Object mLock;
 
@@ -318,6 +320,57 @@
         mDestroyed = true;
     }
 
+    public void dump(FileDescriptor fd, PrintWriter pw, String prefix) {
+        pw.append(prefix).append("user state ").append(String.valueOf(mUserId)).append(":");
+        pw.println();
+
+        String tab = "  ";
+
+        pw.append(prefix).append(tab).append("installed services:").println();
+        final int installedServiceCount = mInstalledServices.size();
+        for (int i = 0; i < installedServiceCount; i++) {
+            PrintServiceInfo installedService = mInstalledServices.get(i);
+            String installedServicePrefix = prefix + tab + tab;
+            pw.append(installedServicePrefix).append("service:").println();
+            ResolveInfo resolveInfo = installedService.getResolveInfo();
+            ComponentName componentName = new ComponentName(
+                    resolveInfo.serviceInfo.packageName,
+                    resolveInfo.serviceInfo.name);
+            pw.append(installedServicePrefix).append(tab).append("componentName=")
+                    .append(componentName.flattenToString()).println();
+            pw.append(installedServicePrefix).append(tab).append("settingsActivity=")
+                    .append(installedService.getSettingsActivityName()).println();
+            pw.append(installedServicePrefix).append(tab).append("addPrintersActivity=")
+                    .append(installedService.getAddPrintersActivityName()).println();
+        }
+
+        pw.append(prefix).append(tab).append("enabled services:").println();
+        for (ComponentName enabledService : mEnabledServices) {
+            String enabledServicePrefix = prefix + tab + tab;
+            pw.append(enabledServicePrefix).append("service:").println();
+            pw.append(enabledServicePrefix).append(tab).append("componentName=")
+                    .append(enabledService.flattenToString());
+            pw.println();
+        }
+
+        pw.append(prefix).append(tab).append("active services:").println();
+        final int activeServiceCount = mActiveServices.size();
+        for (int i = 0; i < activeServiceCount; i++) {
+            RemotePrintService activeService = mActiveServices.valueAt(i);
+            activeService.dump(pw, prefix + tab + tab);
+            pw.println();
+        }
+
+        pw.append(prefix).append(tab).append("discovery mediator:").println();
+        if (mPrinterDiscoverySession != null) {
+            mPrinterDiscoverySession.dump(pw, prefix + tab + tab);
+        }
+
+        pw.append(prefix).append(tab).append("print spooler:").println();
+        mSpooler.dump(fd, pw, prefix + tab + tab);
+        pw.println();
+    }
+
     private boolean readConfigurationLocked() {
         boolean somethingChanged = false;
         somethingChanged |= readInstalledPrintServicesLocked();
@@ -814,6 +867,47 @@
             }
         }
 
+        public void dump(PrintWriter pw, String prefix) {
+            pw.append(prefix).append("destroyed=")
+                    .append(String.valueOf(mDestroyed)).println();
+
+            pw.append(prefix).append("printDiscoveryInProgress=")
+                    .append(String.valueOf(!mStartedPrinterDiscoveryTokens.isEmpty())).println();
+
+            String tab = "  ";
+
+            pw.append(prefix).append(tab).append("printer discovery observers:").println();
+            final int observerCount = mDiscoveryObservers.beginBroadcast();
+            for (int i = 0; i < observerCount; i++) {
+                IPrinterDiscoveryObserver observer = mDiscoveryObservers.getBroadcastItem(i);
+                pw.append(prefix).append(prefix).append(observer.toString());
+                pw.println();
+            }
+            mDiscoveryObservers.finishBroadcast();
+
+            pw.append(prefix).append(tab).append("start discovery requests:").println();
+            final int tokenCount = this.mStartedPrinterDiscoveryTokens.size();
+            for (int i = 0; i < tokenCount; i++) {
+                IBinder token = mStartedPrinterDiscoveryTokens.get(i);
+                pw.append(prefix).append(tab).append(tab).append(token.toString()).println();
+            }
+
+            pw.append(prefix).append(tab).append("tracked printer requests:").println();
+            final int trackedPrinters = mStateTrackedPrinters.size();
+            for (int i = 0; i < trackedPrinters; i++) {
+                PrinterId printer = mStateTrackedPrinters.get(i);
+                pw.append(prefix).append(tab).append(tab).append(printer.toString()).println();
+            }
+
+            pw.append(prefix).append(tab).append("printers:").println();
+            final int pritnerCount = mPrinters.size();
+            for (int i = 0; i < pritnerCount; i++) {
+                PrinterInfo printer = mPrinters.valueAt(i);
+                pw.append(prefix).append(tab).append(tab).append(
+                        printer.toString()).println();
+            }
+        }
+
         private void handleDispatchPrintersAdded(List<PrinterInfo> addedPrinters) {
             final int observerCount = mDiscoveryObservers.beginBroadcast();
             for (int i = 0; i < observerCount; i++) {