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

Commit 94620323 authored by Philip P. Moltmann's avatar Philip P. Moltmann
Browse files

Hold wake lock while printing

more specifically while any print job is
- queued (ready to be printed but not yet printing)
- started (actually printing right now)
- cancelling (printing, but cancel request has been sent)

Test: - Printed successfully
      - Canceled print job
      - Had print job that blocked
      Wake locks looked fine while doing all this
Fixes: 74811014

Change-Id: Ia1a3327bd55fb7f3cc7ecb330d7d2c141d4fdb34
parent ca46c6be
Loading
Loading
Loading
Loading
+9 −0
Original line number Original line Diff line number Diff line
@@ -586,6 +586,15 @@ public final class PrintJobInfo implements Parcelable {
        mCanceling = cancelling;
        mCanceling = cancelling;
    }
    }


    /**
     * If the print job is actively processed, i.e. the device needs to stay on.
     *
     * @hide
     */
    public boolean shouldStayAwake() {
        return mCanceling || mState == STATE_STARTED || mState == STATE_QUEUED;
    }

    /**
    /**
     * Gets whether this job has a given advanced (printer specific) print
     * Gets whether this job has a given advanced (printer specific) print
     * option.
     * option.
+63 −4
Original line number Original line Diff line number Diff line
@@ -16,6 +16,8 @@


package com.android.printspooler.model;
package com.android.printspooler.model;


import static android.os.PowerManager.PARTIAL_WAKE_LOCK;

import static com.android.internal.print.DumpUtils.writePrintJobInfo;
import static com.android.internal.print.DumpUtils.writePrintJobInfo;
import static com.android.internal.util.dump.DumpUtils.writeComponentName;
import static com.android.internal.util.dump.DumpUtils.writeComponentName;


@@ -35,6 +37,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.IBinder;
import android.os.Message;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.RemoteException;
import android.print.IPrintSpooler;
import android.print.IPrintSpooler;
import android.print.IPrintSpoolerCallbacks;
import android.print.IPrintSpoolerCallbacks;
@@ -124,6 +127,9 @@ public final class PrintSpoolerService extends Service {
    /** Cache for custom printer icons loaded from the print service */
    /** Cache for custom printer icons loaded from the print service */
    private CustomPrinterIconCache mCustomIconCache;
    private CustomPrinterIconCache mCustomIconCache;


    /** If the system should be kept awake to process print jobs */
    private PowerManager.WakeLock mKeepAwake;

    public static PrintSpoolerService peekInstance() {
    public static PrintSpoolerService peekInstance() {
        synchronized (sLock) {
        synchronized (sLock) {
            return sInstance;
            return sInstance;
@@ -137,6 +143,8 @@ public final class PrintSpoolerService extends Service {
        mPersistanceManager = new PersistenceManager();
        mPersistanceManager = new PersistenceManager();
        mNotificationController = new NotificationController(PrintSpoolerService.this);
        mNotificationController = new NotificationController(PrintSpoolerService.this);
        mCustomIconCache = new CustomPrinterIconCache(getCacheDir());
        mCustomIconCache = new CustomPrinterIconCache(getCacheDir());
        mKeepAwake = getSystemService(PowerManager.class).newWakeLock(PARTIAL_WAKE_LOCK,
                "Active Print Job");


        synchronized (mLock) {
        synchronized (mLock) {
            mPersistanceManager.readStateLocked();
            mPersistanceManager.readStateLocked();
@@ -480,6 +488,11 @@ public final class PrintSpoolerService extends Service {


    private void addPrintJobLocked(PrintJobInfo printJob) {
    private void addPrintJobLocked(PrintJobInfo printJob) {
        mPrintJobs.add(printJob);
        mPrintJobs.add(printJob);

        if (printJob.shouldStayAwake()) {
            keepAwakeLocked();
        }

        if (DEBUG_PRINT_JOB_LIFECYCLE) {
        if (DEBUG_PRINT_JOB_LIFECYCLE) {
            Slog.i(LOG_TAG, "[ADD] " + printJob);
            Slog.i(LOG_TAG, "[ADD] " + printJob);
        }
        }
@@ -500,6 +513,9 @@ public final class PrintSpoolerService extends Service {
                    persistState = true;
                    persistState = true;
                }
                }
            }
            }

            checkIfStillKeepAwakeLocked();

            if (persistState) {
            if (persistState) {
                mPersistanceManager.writeStateLocked();
                mPersistanceManager.writeStateLocked();
            }
            }
@@ -546,6 +562,12 @@ public final class PrintSpoolerService extends Service {
                printJob.setStatus(error);
                printJob.setStatus(error);
                printJob.setCancelling(false);
                printJob.setCancelling(false);


                if (printJob.shouldStayAwake()) {
                    keepAwakeLocked();
                } else {
                    checkIfStillKeepAwakeLocked();
                }

                if (DEBUG_PRINT_JOB_LIFECYCLE) {
                if (DEBUG_PRINT_JOB_LIFECYCLE) {
                    Slog.i(LOG_TAG, "[STATE CHANGED] " + printJob);
                    Slog.i(LOG_TAG, "[STATE CHANGED] " + printJob);
                }
                }
@@ -717,6 +739,12 @@ public final class PrintSpoolerService extends Service {
                }
                }
                mNotificationController.onUpdateNotifications(mPrintJobs);
                mNotificationController.onUpdateNotifications(mPrintJobs);


                if (printJob.shouldStayAwake()) {
                    keepAwakeLocked();
                } else {
                    checkIfStillKeepAwakeLocked();
                }

                Message message = PooledLambda.obtainMessage(
                Message message = PooledLambda.obtainMessage(
                        PrintSpoolerService::onPrintJobStateChanged, this, printJob);
                        PrintSpoolerService::onPrintJobStateChanged, this, printJob);
                Handler.getMain().executeOrSendMessage(message);
                Handler.getMain().executeOrSendMessage(message);
@@ -1098,7 +1126,7 @@ public final class PrintSpoolerService extends Service {
            try {
            try {
                XmlPullParser parser = Xml.newPullParser();
                XmlPullParser parser = Xml.newPullParser();
                parser.setInput(in, StandardCharsets.UTF_8.name());
                parser.setInput(in, StandardCharsets.UTF_8.name());
                parseState(parser);
                parseStateLocked(parser);
            } catch (IllegalStateException ise) {
            } catch (IllegalStateException ise) {
                Slog.w(LOG_TAG, "Failed parsing ", ise);
                Slog.w(LOG_TAG, "Failed parsing ", ise);
            } catch (NullPointerException npe) {
            } catch (NullPointerException npe) {
@@ -1116,14 +1144,14 @@ public final class PrintSpoolerService extends Service {
            }
            }
        }
        }


        private void parseState(XmlPullParser parser)
        private void parseStateLocked(XmlPullParser parser)
                throws IOException, XmlPullParserException {
                throws IOException, XmlPullParserException {
            parser.next();
            parser.next();
            skipEmptyTextTags(parser);
            skipEmptyTextTags(parser);
            expect(parser, XmlPullParser.START_TAG, TAG_SPOOLER);
            expect(parser, XmlPullParser.START_TAG, TAG_SPOOLER);
            parser.next();
            parser.next();


            while (parsePrintJob(parser)) {
            while (parsePrintJobLocked(parser)) {
                parser.next();
                parser.next();
            }
            }


@@ -1131,7 +1159,7 @@ public final class PrintSpoolerService extends Service {
            expect(parser, XmlPullParser.END_TAG, TAG_SPOOLER);
            expect(parser, XmlPullParser.END_TAG, TAG_SPOOLER);
        }
        }


        private boolean parsePrintJob(XmlPullParser parser)
        private boolean parsePrintJobLocked(XmlPullParser parser)
                throws IOException, XmlPullParserException {
                throws IOException, XmlPullParserException {
            skipEmptyTextTags(parser);
            skipEmptyTextTags(parser);
            if (!accept(parser, XmlPullParser.START_TAG, TAG_JOB)) {
            if (!accept(parser, XmlPullParser.START_TAG, TAG_JOB)) {
@@ -1343,6 +1371,10 @@ public final class PrintSpoolerService extends Service {


            mPrintJobs.add(printJob);
            mPrintJobs.add(printJob);


            if (printJob.shouldStayAwake()) {
                keepAwakeLocked();
            }

            if (DEBUG_PERSISTENCE) {
            if (DEBUG_PERSISTENCE) {
                Log.i(LOG_TAG, "[RESTORED] " + printJob);
                Log.i(LOG_TAG, "[RESTORED] " + printJob);
            }
            }
@@ -1386,6 +1418,33 @@ public final class PrintSpoolerService extends Service {
        }
        }
    }
    }


    /**
     * Keep the system awake as a print job needs to be processed.
     */
    private void keepAwakeLocked() {
        if (!mKeepAwake.isHeld()) {
            mKeepAwake.acquire();
        }
    }

    /**
     * Check if we still need to keep the system awake.
     *
     * @see #keepAwakeLocked
     */
    private void checkIfStillKeepAwakeLocked() {
        if (mKeepAwake.isHeld()) {
            int numPrintJobs = mPrintJobs.size();
            for (int i = 0; i < numPrintJobs; i++) {
                if (mPrintJobs.get(i).shouldStayAwake()) {
                    return;
                }
            }

            mKeepAwake.release();
        }
    }

    public final class PrintSpooler extends IPrintSpooler.Stub {
    public final class PrintSpooler extends IPrintSpooler.Stub {
        @Override
        @Override
        public void getPrintJobInfos(IPrintSpoolerCallbacks callback,
        public void getPrintJobInfos(IPrintSpoolerCallbacks callback,