OSDN Git Service

Merge "Change hasCustomPrintIcon and setStatus as requested by API council." into...
authorPhilip P. Moltmann <moltmann@google.com>
Fri, 25 Mar 2016 16:50:34 +0000 (16:50 +0000)
committerAndroid (Google) Code Review <android-gerrit@google.com>
Fri, 25 Mar 2016 16:50:36 +0000 (16:50 +0000)
14 files changed:
api/current.txt
api/system-current.txt
api/test-current.txt
core/java/android/print/IPrintSpooler.aidl
core/java/android/print/PrintJobInfo.java
core/java/android/print/PrinterInfo.java
core/java/android/printservice/IPrintServiceClient.aidl
core/java/android/printservice/PrintJob.java
core/java/android/printservice/PrintService.java
core/java/com/android/internal/util/Preconditions.java
packages/PrintSpooler/src/com/android/printspooler/model/NotificationController.java
packages/PrintSpooler/src/com/android/printspooler/model/PrintSpoolerService.java
services/print/java/com/android/server/print/RemotePrintService.java
services/print/java/com/android/server/print/RemotePrintSpooler.java

index 99a6430..0177e4f 100644 (file)
@@ -30270,7 +30270,7 @@ package android.print {
     method public android.print.PrinterInfo build();
     method public android.print.PrinterInfo.Builder setCapabilities(android.print.PrinterCapabilitiesInfo);
     method public android.print.PrinterInfo.Builder setDescription(java.lang.String);
-    method public android.print.PrinterInfo.Builder setHasCustomPrinterIcon();
+    method public android.print.PrinterInfo.Builder setHasCustomPrinterIcon(boolean);
     method public android.print.PrinterInfo.Builder setIconResourceId(int);
     method public android.print.PrinterInfo.Builder setInfoIntent(android.app.PendingIntent);
     method public android.print.PrinterInfo.Builder setName(java.lang.String);
@@ -30322,6 +30322,7 @@ package android.printservice {
     method public boolean isStarted();
     method public void setProgress(float);
     method public void setStatus(java.lang.CharSequence);
+    method public void setStatus(int);
     method public boolean setTag(java.lang.String);
     method public boolean start();
   }
index d27923b..7956826 100644 (file)
@@ -32583,7 +32583,7 @@ package android.print {
     method public android.print.PrinterInfo build();
     method public android.print.PrinterInfo.Builder setCapabilities(android.print.PrinterCapabilitiesInfo);
     method public android.print.PrinterInfo.Builder setDescription(java.lang.String);
-    method public android.print.PrinterInfo.Builder setHasCustomPrinterIcon();
+    method public android.print.PrinterInfo.Builder setHasCustomPrinterIcon(boolean);
     method public android.print.PrinterInfo.Builder setIconResourceId(int);
     method public android.print.PrinterInfo.Builder setInfoIntent(android.app.PendingIntent);
     method public android.print.PrinterInfo.Builder setName(java.lang.String);
@@ -32635,6 +32635,7 @@ package android.printservice {
     method public boolean isStarted();
     method public void setProgress(float);
     method public void setStatus(java.lang.CharSequence);
+    method public void setStatus(int);
     method public boolean setTag(java.lang.String);
     method public boolean start();
   }
index 7f16995..264b5eb 100644 (file)
@@ -30262,7 +30262,7 @@ package android.print {
     method public android.print.PrinterId getPrinterId();
     method public float getProgress();
     method public int getState();
-    method public java.lang.CharSequence getStatus();
+    method public java.lang.CharSequence getStatus(android.content.pm.PackageManager);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.print.PrintJobInfo> CREATOR;
     field public static final int STATE_BLOCKED = 4; // 0x4
@@ -30339,7 +30339,7 @@ package android.print {
     method public android.print.PrinterInfo build();
     method public android.print.PrinterInfo.Builder setCapabilities(android.print.PrinterCapabilitiesInfo);
     method public android.print.PrinterInfo.Builder setDescription(java.lang.String);
-    method public android.print.PrinterInfo.Builder setHasCustomPrinterIcon();
+    method public android.print.PrinterInfo.Builder setHasCustomPrinterIcon(boolean);
     method public android.print.PrinterInfo.Builder setIconResourceId(int);
     method public android.print.PrinterInfo.Builder setInfoIntent(android.app.PendingIntent);
     method public android.print.PrinterInfo.Builder setName(java.lang.String);
@@ -30391,6 +30391,7 @@ package android.printservice {
     method public boolean isStarted();
     method public void setProgress(float);
     method public void setStatus(java.lang.CharSequence);
+    method public void setStatus(int);
     method public boolean setTag(java.lang.String);
     method public boolean start();
   }
index 469a4ea..63bf885 100644 (file)
@@ -61,6 +61,15 @@ oneway interface IPrintSpooler {
     void setStatus(in PrintJobId printJobId, in CharSequence status);
 
     /**
+     * Set the status of this print job
+     *
+     * @param printJobId The print job to update
+     * @param status The new status as a string resource
+     * @param appPackageName App package name the resource belongs to
+     */
+    void setStatusRes(in PrintJobId printJobId, int status, in CharSequence appPackageName);
+
+    /**
      * Handle that a custom icon for a printer was loaded.
      *
      * @param printerId the id of the printer the icon belongs to
index 7e3a72f..f134943 100644 (file)
@@ -21,7 +21,10 @@ import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.StringRes;
 import android.annotation.TestApi;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -181,7 +184,11 @@ public final class PrintJobInfo implements Parcelable {
     private float mProgress;
 
     /** A short string describing the status of this job. */
-    private CharSequence mStatus;
+    private @Nullable CharSequence mStatus;
+
+    /** A string resource describing the status of this job. */
+    private @StringRes int mStatusRes;
+    private @Nullable CharSequence mStatusResAppPackageName;
 
     /** Advanced printer specific options. */
     private Bundle mAdvancedOptions;
@@ -210,6 +217,8 @@ public final class PrintJobInfo implements Parcelable {
         mDocumentInfo = other.mDocumentInfo;
         mProgress = other.mProgress;
         mStatus = other.mStatus;
+        mStatusRes = other.mStatusRes;
+        mStatusResAppPackageName = other.mStatusResAppPackageName;
         mCanceling = other.mCanceling;
         mAdvancedOptions = other.mAdvancedOptions;
     }
@@ -235,8 +244,14 @@ public final class PrintJobInfo implements Parcelable {
         mDocumentInfo = (PrintDocumentInfo) parcel.readParcelable(null);
         mProgress = parcel.readFloat();
         mStatus = parcel.readCharSequence();
+        mStatusRes = parcel.readInt();
+        mStatusResAppPackageName = parcel.readCharSequence();
         mCanceling = (parcel.readInt() == 1);
         mAdvancedOptions = parcel.readBundle();
+
+        if (mAdvancedOptions != null) {
+            Preconditions.checkArgument(!mAdvancedOptions.containsKey(null));
+        }
     }
 
     /**
@@ -370,10 +385,28 @@ public final class PrintJobInfo implements Parcelable {
      * @hide
      */
     public void setStatus(@Nullable CharSequence status) {
+        mStatusRes = 0;
+        mStatusResAppPackageName = null;
+
         mStatus = status;
     }
 
     /**
+     * Sets the status of the print job.
+     *
+     * @param status The new status as a string resource
+     * @param appPackageName App package name the resource belongs to
+     *
+     * @hide
+     */
+    public void setStatus(@StringRes int status, @NonNull CharSequence appPackageName) {
+        mStatus = null;
+
+        mStatusRes = status;
+        mStatusResAppPackageName = appPackageName;
+    }
+
+    /**
      * Sets the owning application id.
      *
      * @return The owning app id.
@@ -633,6 +666,8 @@ public final class PrintJobInfo implements Parcelable {
         parcel.writeParcelable(mDocumentInfo, 0);
         parcel.writeFloat(mProgress);
         parcel.writeCharSequence(mStatus);
+        parcel.writeInt(mStatusRes);
+        parcel.writeCharSequence(mStatusResAppPackageName);
         parcel.writeInt(mCanceling ? 1 : 0);
         parcel.writeBundle(mAdvancedOptions);
     }
@@ -659,6 +694,9 @@ public final class PrintJobInfo implements Parcelable {
         builder.append(", progress: " + mProgress);
         builder.append(", status: " + (mStatus != null
                 ? mStatus.toString() : null));
+        builder.append(", statusRes: " + mStatusRes);
+        builder.append(", statusResAppPackageName: " + (mStatusResAppPackageName != null
+                ? mStatusResAppPackageName.toString() : null));
         builder.append("}");
         return builder.toString();
     }
@@ -707,12 +745,23 @@ public final class PrintJobInfo implements Parcelable {
     /**
      * Get the status of this job.
      *
+     * @param pm Package manager used to resolve the string
+     *
      * @return the status of this job or null if not set
      * @hide
      */
     @TestApi
-    public @Nullable CharSequence getStatus() {
-        return mStatus;
+    public @Nullable CharSequence getStatus(@NonNull PackageManager pm) {
+        if (mStatusRes == 0) {
+            return mStatus;
+        } else {
+            try {
+                return pm.getResourcesForApplication(mStatusResAppPackageName.toString())
+                        .getString(mStatusRes);
+            } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) {
+                return null;
+            }
+        }
     }
 
     /**
@@ -789,6 +838,8 @@ public final class PrintJobInfo implements Parcelable {
          * @param value The option value.
          */
         public void putAdvancedOption(@NonNull String key, @Nullable String value) {
+            Preconditions.checkNotNull(key, "key cannot be null");
+
             if (mPrototype.mAdvancedOptions == null) {
                 mPrototype.mAdvancedOptions = new Bundle();
             }
index 0d2d9f4..1ee6389 100644 (file)
@@ -467,10 +467,12 @@ public final class PrinterInfo implements Parcelable {
          * {@link android.printservice.PrinterDiscoverySession#onRequestCustomPrinterIcon}.
          * </p>
          *
+         * @param hasCustomPrinterIcon If the printer has a custom icon or not.
+         *
          * @return This builder.
          */
-        public @NonNull Builder setHasCustomPrinterIcon() {
-            mHasCustomPrinterIcon = true;
+        public @NonNull Builder setHasCustomPrinterIcon(boolean hasCustomPrinterIcon) {
+            mHasCustomPrinterIcon = hasCustomPrinterIcon;
             return this;
         }
 
index 0ae1e18..f0ea6ae 100644 (file)
@@ -52,6 +52,15 @@ interface IPrintServiceClient {
      */
     void setStatus(in PrintJobId printJobId, in CharSequence status);
 
+    /**
+     * Set the status of this print job
+     *
+     * @param printJobId The print job to update
+     * @param status The new status as a string resource
+     * @param appPackageName The app package name the string belongs to
+     */
+    void setStatusRes(in PrintJobId printJobId, int status, in CharSequence appPackageName);
+
     void onPrintersAdded(in ParceledListSlice printers);
     void onPrintersRemoved(in ParceledListSlice printerIds);
 
index 6414b6a..7a7ca23 100644 (file)
@@ -20,11 +20,14 @@ import android.annotation.FloatRange;
 import android.annotation.MainThread;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.StringRes;
+import android.content.Context;
 import android.os.RemoteException;
 import android.print.PrintJobId;
 import android.print.PrintJobInfo;
 import android.text.TextUtils;
 import android.util.Log;
+import com.android.internal.util.Preconditions;
 
 /**
  * This class represents a print job from the perspective of a print
@@ -45,7 +48,12 @@ public final class PrintJob {
 
     private PrintJobInfo mCachedInfo;
 
-    PrintJob(@NonNull PrintJobInfo jobInfo, @NonNull IPrintServiceClient client) {
+    /** Context that created the object */
+    private final Context mContext;
+
+    PrintJob(@NonNull Context context, @NonNull PrintJobInfo jobInfo,
+            @NonNull IPrintServiceClient client) {
+        mContext = context;
         mCachedInfo = jobInfo;
         mPrintServiceClient = client;
         mDocument = new PrintDocument(mCachedInfo.getId(), client,
@@ -216,11 +224,10 @@ public final class PrintJob {
     }
 
     /**
-     * Blocks the print job. You should call this method if {@link
-     * #isStarted()} or {@link #isBlocked()} returns true and you need
-     * to block the print job. For example, the user has to add some
-     * paper to continue printing. To resume the print job call {@link
-     * #start()}.
+     * Blocks the print job. You should call this method if {@link #isStarted()} returns true and
+     * you need to block the print job. For example, the user has to add some paper to continue
+     * printing. To resume the print job call {@link #start()}. To change the reason call
+     * {@link #setStatus(CharSequence)}.
      *
      * @param reason The human readable, short, and translated reason why the print job is blocked.
      * @return Whether the job was blocked.
@@ -233,9 +240,7 @@ public final class PrintJob {
         PrintService.throwIfNotCalledOnMainThread();
         PrintJobInfo info = getInfo();
         final int state = info.getState();
-        if (state == PrintJobInfo.STATE_STARTED
-                || (state == PrintJobInfo.STATE_BLOCKED
-                        && !TextUtils.equals(info.getStatus(), reason))) {
+        if (state == PrintJobInfo.STATE_STARTED || state == PrintJobInfo.STATE_BLOCKED) {
             return setState(PrintJobInfo.STATE_BLOCKED, reason);
         }
         return false;
@@ -320,6 +325,9 @@ public final class PrintJob {
     /**
      * Sets the status of this print job. This should be a human readable, short, and translated
      * description of the current state of the print job.
+     * <p />
+     * This overrides any previously set status set via {@link #setStatus(CharSequence)},
+     * {@link #setStatus(int)}, {@link #block(String)}, or {@link #fail(String)},
      *
      * @param status The new status. If null the status will be empty.
      */
@@ -335,6 +343,29 @@ public final class PrintJob {
     }
 
     /**
+     * Sets the status of this print job as a string resource.
+     * <p />
+     * This overrides any previously set status set via {@link #setStatus(CharSequence)},
+     * {@link #setStatus(int)}, {@link #block(String)}, or {@link #fail(String)},
+     * <p />
+     * To clear the status use {@link #setStatus(CharSequence) <code>setStatus(null)</code>}
+     *
+     * @param status  The new status as a String resource.
+     */
+    @MainThread
+    public void setStatus(@StringRes int status) {
+        PrintService.throwIfNotCalledOnMainThread();
+        Preconditions.checkArgument(status != 0, "status has to be != 0");
+
+        try {
+            mPrintServiceClient.setStatusRes(mCachedInfo.getId(), status,
+                    mContext.getPackageName());
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error setting status for job: " + mCachedInfo.getId(), re);
+        }
+    }
+
+    /**
      * Sets a tag that is valid in the context of a {@link PrintService}
      * and is not interpreted by the system. For example, a print service
      * may set as a tag the key of the print job returned by a remote
index 62d214e..8f73518 100644 (file)
@@ -329,7 +329,7 @@ public abstract class PrintService extends Service {
                 final int printJobInfoCount = printJobInfos.size();
                 printJobs = new ArrayList<PrintJob>(printJobInfoCount);
                 for (int i = 0; i < printJobInfoCount; i++) {
-                    printJobs.add(new PrintJob(printJobInfos.get(i), mClient));
+                    printJobs.add(new PrintJob(this, printJobInfos.get(i), mClient));
                 }
             }
             if (printJobs != null) {
@@ -549,7 +549,7 @@ public abstract class PrintService extends Service {
                                 + getPackageName());
                     }
                     PrintJobInfo printJobInfo = (PrintJobInfo) message.obj;
-                    onRequestCancelPrintJob(new PrintJob(printJobInfo, mClient));
+                    onRequestCancelPrintJob(new PrintJob(PrintService.this, printJobInfo, mClient));
                 } break;
 
                 case MSG_ON_PRINTJOB_QUEUED: {
@@ -561,7 +561,7 @@ public abstract class PrintService extends Service {
                     if (DEBUG) {
                         Log.i(LOG_TAG, "Queued: " + printJobInfo);
                     }
-                    onPrintJobQueued(new PrintJob(printJobInfo, mClient));
+                    onPrintJobQueued(new PrintJob(PrintService.this, printJobInfo, mClient));
                 } break;
 
                 case MSG_SET_CLIENT: {
index 53cb56e..c46851e 100644 (file)
@@ -35,6 +35,20 @@ public class Preconditions {
     }
 
     /**
+     * Ensures that an expression checking an argument is true.
+     *
+     * @param expression the expression to check
+     * @param errorMessage the exception message to use if the check fails; will
+     *     be converted to a string using {@link String#valueOf(Object)}
+     * @throws IllegalArgumentException if {@code expression} is false
+     */
+    public static void checkArgument(boolean expression, final Object errorMessage) {
+        if (!expression) {
+            throw new IllegalArgumentException(String.valueOf(errorMessage));
+        }
+    }
+
+    /**
      * Ensures that an string reference passed as a parameter to the calling
      * method is not empty.
      *
index 0210693..cd1d540 100644 (file)
@@ -208,7 +208,7 @@ final class NotificationController {
             }
         }
 
-        CharSequence status = printJob.getStatus();
+        CharSequence status = printJob.getStatus(mContext.getPackageManager());
         if (status != null) {
             builder.setContentText(status);
         } else {
index d2b4d1b..9b1ab0e 100644 (file)
@@ -19,6 +19,7 @@ package com.android.printspooler.model;
 import android.annotation.FloatRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.StringRes;
 import android.app.Service;
 import android.content.ComponentName;
 import android.content.Context;
@@ -575,19 +576,35 @@ public final class PrintSpoolerService extends Service {
         }
     }
 
-   /**
-    * Set the status for a print job.
-    *
-    * @param printJobId ID of the print job to update
-    * @param status the new status
-    */
-   public void setStatus(@NonNull PrintJobId printJobId, @Nullable CharSequence status) {
-       synchronized (mLock) {
-           getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY).setStatus(status);
+    /**
+     * Set the status for a print job.
+     *
+     * @param printJobId ID of the print job to update
+     * @param status the new status
+     */
+    public void setStatus(@NonNull PrintJobId printJobId, @Nullable CharSequence status) {
+        synchronized (mLock) {
+            getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY).setStatus(status);
+
+            mNotificationController.onUpdateNotifications(mPrintJobs);
+        }
+    }
+
+    /**
+     * Set the status for a print job.
+     *
+     * @param printJobId ID of the print job to update
+     * @param status the new status as a string resource
+     * @param appPackageName app package the resource belongs to
+     */
+    public void setStatus(@NonNull PrintJobId printJobId, @StringRes int status,
+            @Nullable CharSequence appPackageName) {
+        synchronized (mLock) {
+            getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY).setStatus(status, appPackageName);
 
-           mNotificationController.onUpdateNotifications(mPrintJobs);
-       }
-   }
+            mNotificationController.onUpdateNotifications(mPrintJobs);
+        }
+    }
 
     public boolean hasActivePrintJobsLocked() {
         final int printJobCount = mPrintJobs.size();
@@ -884,7 +901,7 @@ public final class PrintSpoolerService extends Service {
                         serializer.attribute(null, ATTR_PROGRESS, String.valueOf(progress));
                     }
 
-                    CharSequence status = printJob.getStatus();
+                    CharSequence status = printJob.getStatus(getPackageManager());
                     if (!TextUtils.isEmpty(status)) {
                         serializer.attribute(null, ATTR_STATUS, status.toString());
                     }
@@ -1435,6 +1452,13 @@ public final class PrintSpoolerService extends Service {
             PrintSpoolerService.this.setStatus(printJobId, status);
         }
 
+        @Override
+        public void setStatusRes(@NonNull PrintJobId printJobId, @StringRes int status,
+                @NonNull CharSequence appPackageName) throws RemoteException {
+            PrintSpoolerService.this.setStatus(printJobId, status, appPackageName);
+        }
+
+
         public PrintSpoolerService getService() {
             return PrintSpoolerService.this;
         }
index 9b99c67..9c3a852 100644 (file)
@@ -19,6 +19,7 @@ package com.android.server.print;
 import android.annotation.FloatRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.StringRes;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -813,6 +814,20 @@ final class RemotePrintService implements DeathRecipient {
         }
 
         @Override
+        public void setStatusRes(@NonNull PrintJobId printJobId, @StringRes int status,
+                @NonNull CharSequence appPackageName) {
+            RemotePrintService service = mWeakService.get();
+            if (service != null) {
+                final long identity = Binder.clearCallingIdentity();
+                try {
+                    service.mSpooler.setStatus(printJobId, status, appPackageName);
+                } finally {
+                    Binder.restoreCallingIdentity(identity);
+                }
+            }
+        }
+
+        @Override
         @SuppressWarnings({"rawtypes", "unchecked"})
         public void onPrintersAdded(ParceledListSlice printers) {
             RemotePrintService service = mWeakService.get();
index e1d8c6c..be822c8 100644 (file)
@@ -19,6 +19,7 @@ package com.android.server.print;
 import android.annotation.FloatRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.StringRes;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -301,6 +302,35 @@ final class RemotePrintSpooler {
     }
 
     /**
+     * Set status of a print job.
+     *
+     * @param printJobId The print job to update
+     * @param status The new status as a string resource
+     * @param appPackageName The app package name the string res belongs to
+     */
+    public final void setStatus(@NonNull PrintJobId printJobId, @StringRes int status,
+            @NonNull CharSequence appPackageName) {
+        throwIfCalledOnMainThread();
+        synchronized (mLock) {
+            throwIfDestroyedLocked();
+            mCanUnbind = false;
+        }
+        try {
+            getRemoteInstanceLazy().setStatusRes(printJobId, status, appPackageName);
+        } catch (RemoteException|TimeoutException re) {
+            Slog.e(LOG_TAG, "Error setting status.", re);
+        } finally {
+            if (DEBUG) {
+                Slog.i(LOG_TAG, "[user: " + mUserHandle.getIdentifier() + "] setStatus()");
+            }
+            synchronized (mLock) {
+                mCanUnbind = true;
+                mLock.notifyAll();
+            }
+        }
+    }
+
+    /**
      * Handle that a custom icon for a printer was loaded.
      *
      * @param printerId the id of the printer the icon belongs to