Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7bb1be4b authored by Svetoslav Ganov's avatar Svetoslav Ganov Committed by Android (Google) Code Review
Browse files

Merge "Polish the print spooler loading of stored print jobs."

parents f76ff055 835835ee
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -46,5 +46,4 @@ oneway interface IPrintSpooler {
            int sequence);
    void writePrintJobData(in ParcelFileDescriptor fd, int printJobId);
    void setClient(IPrintSpoolerClient client);
    void notifyClientForActivteJobs();
}
+90 −69
Original line number Diff line number Diff line
@@ -22,7 +22,10 @@ import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Build;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
@@ -43,6 +46,8 @@ public class NotificationController {
    private static final String INTENT_ACTION_CANCEL_PRINTJOB = "INTENT_ACTION_CANCEL_PRINTJOB";
    private static final String INTENT_ACTION_RESTART_PRINTJOB = "INTENT_ACTION_RESTART_PRINTJOB";
    private static final String INTENT_EXTRA_PRINTJOB_ID = "INTENT_EXTRA_PRINTJOB_ID";
    private static final String INTENT_EXTRA_PRINTJOB_LABEL = "INTENT_EXTRA_PRINTJOB_LABEL";
    private static final String INTENT_EXTRA_PRINTER_NAME = "INTENT_EXTRA_PRINTER_NAME";

    private final Context mContext;
    private final NotificationManager mNotificationManager;
@@ -53,11 +58,10 @@ public class NotificationController {
                mContext.getSystemService(Context.NOTIFICATION_SERVICE);
    }

    public void onPrintJobStateChanged(PrintJobInfo printJob, int oldState) {
    public void onPrintJobStateChanged(PrintJobInfo printJob) {
        if (DEBUG) {
            Log.i(LOG_TAG, "onPrintJobStateChanged() printJobId: " + printJob.getId()
                    + " oldState: " + PrintJobInfo.stateToString(oldState)
                    + " newState:" + PrintJobInfo.stateToString(printJob.getState()));
                    + " state:" + PrintJobInfo.stateToString(printJob.getState()));
        }
        switch (printJob.getState()) {
            case PrintJobInfo.STATE_QUEUED: {
@@ -87,10 +91,10 @@ public class NotificationController {
                        printJob.getLabel()))
                // TODO: Use appropriate icon when assets are ready
                .addAction(android.R.drawable.ic_secure, mContext.getString(R.string.cancel),
                        createCancelIntent(printJob.getId()))
                        createCancelIntent(printJob))
                .setContentText(printJob.getPrinterId().getPrinterName())
                .setOngoing(true)
                .setWhen(System.currentTimeMillis())
                .setOngoing(true)
                .setShowWhen(true);
        mNotificationManager.notify(printJob.getId(), builder.build());
    }
@@ -103,10 +107,10 @@ public class NotificationController {
                        printJob.getLabel()))
                // TODO: Use appropriate icon when assets are ready
                .addAction(android.R.drawable.ic_secure, mContext.getString(R.string.cancel),
                        createCancelIntent(printJob.getId()))
                        createCancelIntent(printJob))
                .setContentText(printJob.getPrinterId().getPrinterName())
                .setOngoing(true)
                .setWhen(System.currentTimeMillis())
                .setOngoing(true)
                .setShowWhen(true);
        mNotificationManager.notify(printJob.getId(), builder.build());
    }
@@ -119,13 +123,13 @@ public class NotificationController {
                        printJob.getLabel()))
                // TODO: Use appropriate icon when assets are ready
                .addAction(android.R.drawable.ic_secure, mContext.getString(R.string.cancel),
                        createCancelIntent(printJob.getId()))
                        createCancelIntent(printJob))
                // TODO: Use appropriate icon when assets are ready
                .addAction(android.R.drawable.ic_secure, mContext.getString(R.string.restart),
                        createRestartIntent(printJob.getId()))
                .setContentText(printJob.getFailureReason())
                .setOngoing(true)
                .setWhen(System.currentTimeMillis())
                .setOngoing(true)
                .setShowWhen(true);
        mNotificationManager.notify(printJob.getId(), builder.build());
    }
@@ -134,10 +138,12 @@ public class NotificationController {
        mNotificationManager.cancel(printJobId);
    }

    private PendingIntent createCancelIntent(int printJobId) {
    private PendingIntent createCancelIntent(PrintJobInfo printJob) {
        Intent intent = new Intent(mContext, NotificationBroadcastReceiver.class);
        intent.setAction(INTENT_ACTION_CANCEL_PRINTJOB + "_" + String.valueOf(printJobId));
        intent.putExtra(INTENT_EXTRA_PRINTJOB_ID, printJobId);
        intent.setAction(INTENT_ACTION_CANCEL_PRINTJOB + "_" + String.valueOf(printJob.getId()));
        intent.putExtra(INTENT_EXTRA_PRINTJOB_ID, printJob.getId());
        intent.putExtra(INTENT_EXTRA_PRINTJOB_LABEL, printJob.getLabel());
        intent.putExtra(INTENT_EXTRA_PRINTER_NAME, printJob.getPrinterId().getPrinterName());
        return PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT);
    }

@@ -156,44 +162,48 @@ public class NotificationController {
            String action = intent.getAction();
            if (action != null && action.startsWith(INTENT_ACTION_CANCEL_PRINTJOB)) {
                final int printJobId = intent.getExtras().getInt(INTENT_EXTRA_PRINTJOB_ID);
                handleCancelPrintJob(context, printJobId);
                String printJobLabel = intent.getExtras().getString(INTENT_EXTRA_PRINTJOB_LABEL);
                String printerName = intent.getExtras().getString(INTENT_EXTRA_PRINTER_NAME);
                handleCancelPrintJob(context, printJobId, printJobLabel, printerName);
            } else if (action != null && action.startsWith(INTENT_ACTION_RESTART_PRINTJOB)) {
                final int printJobId = intent.getExtras().getInt(INTENT_EXTRA_PRINTJOB_ID);
                handleRestartPrintJob(context, printJobId);
            }
        }

        private void handleCancelPrintJob(final Context context, final int printJobId) {
        private void handleCancelPrintJob(final Context context, final int printJobId,
                final String printJobLabel, final String printerName) {
            if (DEBUG) {
                Log.i(LOG_TAG, "handleCancelPrintJob() printJobId:" + printJobId);
            }

            PrintSpooler printSpooler = PrintSpooler.getInstance(context);

            final PrintJobInfo printJob = printSpooler.getPrintJobInfo(printJobId,
                    PrintManager.APP_ID_ANY);

            if (printJob == null || printJob.getState() == PrintJobInfo.STATE_CANCELED) {
                return;
            }

            // Put up a notification that we are trying to cancel.
            NotificationManager notificationManager = (NotificationManager)
                    context.getSystemService(Context.NOTIFICATION_SERVICE);

            Notification.Builder builder = new Notification.Builder(context)
                    // TODO: Use appropriate icon when assets are ready
                    .setSmallIcon(android.R.drawable.ic_secure)
                    .setContentTitle(context.getString(
                            R.string.cancelling_notification_title_template,
                            printJob.getLabel()))
                    .setContentText(printJob.getPrinterId().getPrinterName())
                    .setOngoing(true)
                            printJobLabel))
                    .setContentText(printerName)
                    .setWhen(System.currentTimeMillis())
                    .setOngoing(true)
                    .setShowWhen(true);

            notificationManager.notify(printJob.getId(), builder.build());

            notificationManager.notify(printJobId, builder.build());

            // Call into the print manager service off the main thread since
            // the print manager service may end up binding to the print spooler
            // service which binding is handled on the main thread.
            PowerManager powerManager = (PowerManager)
                    context.getSystemService(Context.POWER_SERVICE);
            final WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                    LOG_TAG);
            wakeLock.acquire();

            new AsyncTask<Void, Void, Void>() {
                @Override
                protected Void doInBackground(Void... params) {
                    // We need to request the cancellation to be done by the print
                    // manager service since it has to communicate with the managing
                    // print service to request the cancellation. Also we need the
@@ -201,15 +211,19 @@ public class NotificationController {
                    // print job will trigger persistence of current jobs which is
                    // done on another thread and until it finishes the spooler has
                    // to be kept around.
                    try {
                    IPrintManager printManager = IPrintManager.Stub.asInterface(
                            ServiceManager.getService(Context.PRINT_SERVICE));

            try {
                        printManager.cancelPrintJob(printJobId, PrintManager.APP_ID_ANY,
                                UserHandle.myUserId());
                    } catch (RemoteException re) {
                        Log.i(LOG_TAG, "Error requestion print job cancellation", re);
                    } finally {
                        wakeLock.release();
                    }
                    return null;
                }
            }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
        }

        private void handleRestartPrintJob(final Context context, final int printJobId) {
@@ -217,29 +231,36 @@ public class NotificationController {
                Log.i(LOG_TAG, "handleRestartPrintJob() printJobId:" + printJobId);
            }

            PrintSpooler printSpooler = PrintSpooler.getInstance(context);

            PrintJobInfo printJob = printSpooler.getPrintJobInfo(printJobId,
                    PrintManager.APP_ID_ANY);

            if (printJob == null || printJob.getState() != PrintJobInfo.STATE_FAILED) {
                return;
            }
            // Call into the print manager service off the main thread since
            // the print manager service may end up binding to the print spooler
            // service which binding is handled on the main thread.
            PowerManager powerManager = (PowerManager)
                    context.getSystemService(Context.POWER_SERVICE);
            final WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                    LOG_TAG);
            wakeLock.acquire();

            new AsyncTask<Void, Void, Void>() {
                @Override
                protected Void doInBackground(Void... params) {
                    // We need to request the restart to be done by the print manager
                    // service since the latter must be bound to the spooler because
                    // restarting a print job will trigger persistence of current jobs
                    // which is done on another thread and until it finishes the spooler has
                    // to be kept around.
                    try {
                        IPrintManager printManager = IPrintManager.Stub.asInterface(
                                ServiceManager.getService(Context.PRINT_SERVICE));

            try {
                        printManager.restartPrintJob(printJobId, PrintManager.APP_ID_ANY,
                                UserHandle.myUserId());
                    } catch (RemoteException re) {
                        Log.i(LOG_TAG, "Error requestion print job restart", re);
                    } finally {
                        wakeLock.release();
                    }
                    return null;
                }
            }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
        }
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -161,7 +161,7 @@ public class PrintJobConfigActivity extends Activity {
            mCurrPrintAttributes.copyFrom(attributes);
        }

        mSpooler = PrintSpooler.getInstance(this);
        mSpooler = PrintSpooler.peekInstance();
        mEditor = new Editor();
        mDocument = new Document();
        mController = new PrintController(new RemotePrintDocumentAdapter(
+85 −265

File changed.

Preview size limit exceeded, changes collapsed.

+161 −36
Original line number Diff line number Diff line
@@ -16,8 +16,6 @@

package com.android.printspooler;

import java.util.List;

import android.app.PendingIntent;
import android.app.Service;
import android.content.ComponentName;
@@ -29,44 +27,48 @@ import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.print.IPrintDocumentAdapter;
import android.print.IPrintClient;
import android.print.IPrintSpoolerClient;
import android.print.IPrintDocumentAdapter;
import android.print.IPrintSpooler;
import android.print.IPrintSpoolerCallbacks;
import android.print.IPrintSpoolerClient;
import android.print.IPrinterDiscoveryObserver;
import android.print.PrintAttributes;
import android.print.PrintJobInfo;
import android.print.PrinterId;
import android.util.Log;
import android.util.Slog;

import com.android.internal.os.SomeArgs;

import java.util.List;

/**
 * Service for exposing some of the {@link PrintSpooler} functionality to
 * another process.
 */
public final class PrintSpoolerService extends Service {

    private static final long CHECK_ALL_PRINTJOBS_HANDLED_DELAY = 5000;

    private static final String LOG_TAG = "PrintSpoolerService";

    private Intent mStartPrintJobConfigActivityIntent;

    private PrintSpooler mSpooler;
    private IPrintSpoolerClient mClient;

    private Handler mHanlder;
    private Handler mHandler;

    @Override
    public void onCreate() {
        super.onCreate();
        mStartPrintJobConfigActivityIntent = new Intent(PrintSpoolerService.this,
                PrintJobConfigActivity.class);
        mSpooler = PrintSpooler.getInstance(this);
        mHanlder = new MyHandler(getMainLooper());
        mHandler = new MyHandler(getMainLooper());
    }

    @Override
    public IBinder onBind(Intent intent) {
        mSpooler.restorePersistedState();

        return new IPrintSpooler.Stub() {
            @Override
            public void getPrintJobInfos(IPrintSpoolerCallbacks callback,
@@ -74,7 +76,8 @@ public final class PrintSpoolerService extends Service {
                            throws RemoteException {
                List<PrintJobInfo> printJobs = null;
                try {
                    printJobs = mSpooler.getPrintJobInfos(componentName, state, appId);
                    printJobs = PrintSpooler.peekInstance().getPrintJobInfos(
                            componentName, state, appId);
                } finally {
                    callback.onGetPrintJobInfosResult(printJobs, sequence);
                }
@@ -85,7 +88,7 @@ public final class PrintSpoolerService extends Service {
                    int appId, int sequence) throws RemoteException {
                PrintJobInfo printJob = null;
                try {
                    printJob = mSpooler.getPrintJobInfo(printJobId, appId);
                    printJob = PrintSpooler.peekInstance().getPrintJobInfo(printJobId, appId);
                } finally {
                    callback.onGetPrintJobInfoResult(printJob, sequence);
                }
@@ -99,7 +102,7 @@ public final class PrintSpoolerService extends Service {
                            throws RemoteException {
                PrintJobInfo printJob = null;
                try {
                    printJob = mSpooler.createPrintJob(printJobName, client,
                    printJob = PrintSpooler.peekInstance().createPrintJob(printJobName, client,
                            attributes, appId);
                    if (printJob != null) {
                        Intent intent = mStartPrintJobConfigActivityIntent;
@@ -116,7 +119,8 @@ public final class PrintSpoolerService extends Service {
                        SomeArgs args = SomeArgs.obtain();
                        args.arg1 = client;
                        args.arg2 = sender;
                        mHanlder.obtainMessage(0, args).sendToTarget();
                        mHandler.obtainMessage(MyHandler.MSG_START_PRINT_JOB_CONFIG_ACTIVITY,
                                args).sendToTarget();
                    }
                } finally {
                    callback.onCreatePrintJobResult(printJob, sequence);
@@ -128,7 +132,8 @@ public final class PrintSpoolerService extends Service {
                    IPrintSpoolerCallbacks callback, int sequece) throws RemoteException {
                boolean success = false;
                try {
                    success = mSpooler.setPrintJobState(printJobId, state, error);
                    success = PrintSpooler.peekInstance().setPrintJobState(
                            printJobId, state, error);
                } finally {
                    callback.onSetPrintJobStateResult(success, sequece);
                }
@@ -136,11 +141,10 @@ public final class PrintSpoolerService extends Service {

            @Override
            public void setPrintJobTag(int printJobId, String tag,
                    IPrintSpoolerCallbacks callback, int sequece)
                            throws RemoteException {
                    IPrintSpoolerCallbacks callback, int sequece) throws RemoteException {
                boolean success = false;
                try {
                    success = mSpooler.setPrintJobTag(printJobId, tag);
                    success = PrintSpooler.peekInstance().setPrintJobTag(printJobId, tag);
                } finally {
                    callback.onSetPrintJobTagResult(success, sequece);
                }
@@ -148,29 +152,76 @@ public final class PrintSpoolerService extends Service {

            @Override
            public void writePrintJobData(ParcelFileDescriptor fd, int printJobId) {
                mSpooler.writePrintJobData(fd, printJobId);
                PrintSpooler.peekInstance().writePrintJobData(fd, printJobId);
            }

            @Override
            public void setClient(IPrintSpoolerClient client) {
                mSpooler.setCleint(client);
                mHandler.obtainMessage(MyHandler.MSG_SET_CLIENT, client).sendToTarget();
            }
        };
    }

            @Override
            public void notifyClientForActivteJobs() {
                mSpooler.notifyClientForActivteJobs();
    public void onPrintJobQueued(PrintJobInfo printJob) {
        mHandler.obtainMessage(MyHandler.MSG_ON_PRINT_JOB_QUEUED,
                printJob).sendToTarget();
    }
        };

    public void onReqeustUpdatePrinters(List<PrinterId> printers) {
        mHandler.obtainMessage(MyHandler.MSG_ON_REQUEST_UPDATE_PRINTERS,
                printers).sendToTarget();
    }

    public void startPrinterDiscovery(IPrinterDiscoveryObserver observer) {
        mHandler.obtainMessage(MyHandler.MSG_ON_START_PRINTER_DISCOVERY,
                observer).sendToTarget();
    }

    private static final class MyHandler extends Handler {
    public void stopPrinterDiscovery() {
        mHandler.sendEmptyMessage(MyHandler.MSG_ON_STOP_PRINTER_DISCOVERY);
    }

    public void onAllPrintJobsForServiceHandled(ComponentName service) {
        mHandler.obtainMessage(MyHandler.MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED,
                service).sendToTarget();
    }

    public void onAllPrintJobsHandled() {
        mHandler.sendEmptyMessage(MyHandler.MSG_ON_ALL_PRINT_JOBS_HANDLED);
    }

    private final class MyHandler extends Handler {
        public static final int MSG_SET_CLIENT = 1;
        public static final int MSG_START_PRINT_JOB_CONFIG_ACTIVITY = 2;
        public static final int MSG_ON_START_PRINTER_DISCOVERY = 3;
        public static final int MSG_ON_STOP_PRINTER_DISCOVERY = 4;
        public static final int MSG_ON_PRINT_JOB_QUEUED = 5;
        public static final int MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED = 6;
        public static final int MSG_ON_ALL_PRINT_JOBS_HANDLED = 7;
        public static final int MSG_ON_REQUEST_UPDATE_PRINTERS = 8;
        public static final int MSG_CHECK_ALL_PRINTJOBS_HANDLED = 9;

        public MyHandler(Looper looper) {
            super(looper, null, true);
            super(looper, null, false);
        }

        @Override
        @SuppressWarnings("unchecked")
        public void handleMessage(Message message) {
            switch (message.what) {
                case MSG_SET_CLIENT: {
                    mClient = (IPrintSpoolerClient) message.obj;
                    if (mClient != null) {
                        PrintSpooler.createInstance(PrintSpoolerService.this);
                        mHandler.sendEmptyMessageDelayed(
                                MyHandler.MSG_CHECK_ALL_PRINTJOBS_HANDLED,
                                CHECK_ALL_PRINTJOBS_HANDLED_DELAY);
                    } else {
                        PrintSpooler.destroyInstance();
                    }
                } break;

                case MSG_START_PRINT_JOB_CONFIG_ACTIVITY: {
                    SomeArgs args = (SomeArgs) message.obj;
                    IPrintClient client = (IPrintClient) args.arg1;
                    IntentSender sender = (IntentSender) args.arg2;
@@ -180,6 +231,80 @@ public final class PrintSpoolerService extends Service {
                    } catch (RemoteException re) {
                        Slog.i(LOG_TAG, "Error starting print job config activity!", re);
                    }
                } break;

                case MSG_ON_START_PRINTER_DISCOVERY: {
                    IPrinterDiscoveryObserver observer = (IPrinterDiscoveryObserver) message.obj;
                    if (mClient != null) {
                        try {
                            mClient.onStartPrinterDiscovery(observer);
                        } catch (RemoteException re) {
                            Log.e(LOG_TAG, "Error notifying start printer discovery.", re);
                        }
                    }
                } break;

                case MSG_ON_STOP_PRINTER_DISCOVERY: {
                    if (mClient != null) {
                        try {
                            mClient.onStopPrinterDiscovery();
                        } catch (RemoteException re) {
                            Log.e(LOG_TAG, "Error notifying stop printer discovery.", re);
                        }
                    }
                } break;

                case MSG_ON_PRINT_JOB_QUEUED: {
                    PrintJobInfo printJob = (PrintJobInfo) message.obj;
                    if (mClient != null) {
                        try {
                            mClient.onPrintJobQueued(printJob);
                        } catch (RemoteException re) {
                            Slog.e(LOG_TAG, "Error notify for a queued print job.", re);
                        }
                    }
                } break;

                case MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED: {
                    ComponentName service = (ComponentName) message.obj;
                    if (mClient != null) {
                        try {
                            mClient.onAllPrintJobsForServiceHandled(service);
                        } catch (RemoteException re) {
                            Slog.e(LOG_TAG, "Error notify for all print jobs per service"
                                    + " handled.", re);
                        }
                    }
                } break;

                case MSG_ON_ALL_PRINT_JOBS_HANDLED: {
                    if (mClient != null) {
                        try {
                            mClient.onAllPrintJobsHandled();
                        } catch (RemoteException re) {
                            Slog.e(LOG_TAG, "Error notify for all print job handled.", re);
                        }
                    }
                } break;

                case MSG_ON_REQUEST_UPDATE_PRINTERS: {
                    List<PrinterId> printerIds = (List<PrinterId>) message.obj;
                    if (mClient != null) {
                        try {
                            mClient.onRequestUpdatePrinters(printerIds);
                        } catch (RemoteException re) {
                            Slog.e(LOG_TAG, "Error requesting to update pritners.", re);
                        }
                    }
                } break;

                case MSG_CHECK_ALL_PRINTJOBS_HANDLED: {
                    PrintSpooler spooler = PrintSpooler.peekInstance();
                    if (spooler != null) {
                        spooler.checkAllPrintJobsHandled();
                    }
                } break;
            }
        }
    }
}
Loading