0

android: Add @NullMarked to //printing

Added manual changes to avoid @NullUnmarked.

Added a constructor to PrintDocumentAdapterWrapper as setPdfGenerator
was only used in one spot, and that was right after calling the
constructor. This simplifies the code and ensures that mPdfGenerator is
never null.

Bug: 40657579
Change-Id: I992c67a35ab945a1f8f44e8aa3534055c1ca869c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6106312
Reviewed-by: Sam Maier <smaier@chromium.org>
Auto-Submit: Peter Wen <wnwen@chromium.org>
Commit-Queue: Peter Wen <wnwen@chromium.org>
Owners-Override: Peter Wen <wnwen@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1398054}
This commit is contained in:
Peter Wen
2024-12-18 10:14:09 -08:00
committed by Chromium LUCI CQ
parent 26a14387e6
commit 1b29bb1ff6
7 changed files with 69 additions and 37 deletions

@ -12,6 +12,9 @@ import android.print.PrintAttributes;
import android.print.PrintDocumentAdapter;
import android.print.PrintDocumentInfo;
import org.chromium.build.annotations.NullMarked;
import org.chromium.build.annotations.Nullable;
/**
* Wrapper for {@link PrintDocumentAdapter} for easier testing.
*
@ -21,9 +24,14 @@ import android.print.PrintDocumentInfo;
* {@link PrintDocumentAdapter#onLayout} and {@link PrintDocumentAdapter#onWrite}. This class helps
* bypassing the limitation.
*/
@NullMarked
public class PrintDocumentAdapterWrapper extends PrintDocumentAdapter {
private PdfGenerator mPdfGenerator;
public PrintDocumentAdapterWrapper(PdfGenerator pdfGenerator) {
mPdfGenerator = pdfGenerator;
}
public static interface PdfGenerator {
void onStart();
@ -32,7 +40,7 @@ public class PrintDocumentAdapterWrapper extends PrintDocumentAdapter {
PrintAttributes newAttributes,
CancellationSignal cancellationSignal,
PrintDocumentAdapterWrapper.LayoutResultCallbackWrapper callback,
Bundle metadata);
@Nullable Bundle metadata);
void onWrite(
final PageRange[] ranges,
@ -46,7 +54,7 @@ public class PrintDocumentAdapterWrapper extends PrintDocumentAdapter {
public static interface LayoutResultCallbackWrapper {
void onLayoutFinished(PrintDocumentInfo info, boolean changed);
void onLayoutFailed(CharSequence error);
void onLayoutFailed(@Nullable CharSequence error);
void onLayoutCancelled();
}
@ -54,7 +62,7 @@ public class PrintDocumentAdapterWrapper extends PrintDocumentAdapter {
public static interface WriteResultCallbackWrapper {
void onWriteFinished(PageRange[] pages);
void onWriteFailed(CharSequence error);
void onWriteFailed(@Nullable CharSequence error);
void onWriteCancelled();
}
@ -73,7 +81,7 @@ public class PrintDocumentAdapterWrapper extends PrintDocumentAdapter {
}
@Override
public void onLayoutFailed(CharSequence error) {
public void onLayoutFailed(@Nullable CharSequence error) {
mCallback.onLayoutFailed(error);
}
@ -97,7 +105,7 @@ public class PrintDocumentAdapterWrapper extends PrintDocumentAdapter {
}
@Override
public void onWriteFailed(CharSequence error) {
public void onWriteFailed(@Nullable CharSequence error) {
mCallback.onWriteFailed(error);
}
@ -107,10 +115,6 @@ public class PrintDocumentAdapterWrapper extends PrintDocumentAdapter {
}
}
public void setPdfGenerator(PdfGenerator pdfGenerator) {
mPdfGenerator = pdfGenerator;
}
/** Initiates the printing process within the framework */
public void print(PrintManagerDelegate printManager, String title) {
printManager.print(title, this, null);

@ -7,10 +7,14 @@ package org.chromium.printing;
import android.print.PrintAttributes;
import android.print.PrintDocumentAdapter;
import org.chromium.build.annotations.NullMarked;
import org.chromium.build.annotations.Nullable;
/**
* Defines an interface for the Android system printing service, for easier testing.
* We can't simply extend from {@link android.print.PrintManager}, since it's a final class.
*/
@NullMarked
public interface PrintManagerDelegate {
/**
@ -18,5 +22,7 @@ public interface PrintManagerDelegate {
* {@link android.print.PrintJob} since the clients don't need it.
*/
void print(
String printJobName, PrintDocumentAdapter documentAdapter, PrintAttributes attributes);
String printJobName,
PrintDocumentAdapter documentAdapter,
@Nullable PrintAttributes attributes);
}

@ -14,10 +14,13 @@ import android.print.PrintManager;
import android.text.TextUtils;
import org.chromium.base.Log;
import org.chromium.build.annotations.NullMarked;
import org.chromium.build.annotations.Nullable;
import java.util.List;
/** An implementation of {@link PrintManagerDelegate} using the Android framework print manager. */
@NullMarked
public class PrintManagerDelegateImpl implements PrintManagerDelegate {
private static final String TAG = "printing";
private final PrintManager mPrintManager;
@ -28,7 +31,9 @@ public class PrintManagerDelegateImpl implements PrintManagerDelegate {
@Override
public void print(
String printJobName, PrintDocumentAdapter documentAdapter, PrintAttributes attributes) {
String printJobName,
PrintDocumentAdapter documentAdapter,
@Nullable PrintAttributes attributes) {
dumpJobStatesForDebug();
mPrintManager.print(printJobName, documentAdapter, attributes);
}

@ -4,11 +4,14 @@
package org.chromium.printing;
import org.chromium.build.annotations.NullMarked;
/**
* Describes a class that can initiate the printing process.
*
* This interface helps decoupling Tab from the printing implementation and helps with testing.
*/
@NullMarked
public interface Printable {
/** Start the PDF generation process. */
boolean print(int renderProcessId, int renderFrameId);

@ -11,6 +11,8 @@ import org.jni_zero.JNINamespace;
import org.jni_zero.NativeMethods;
import org.chromium.base.ThreadUtils;
import org.chromium.build.annotations.NullMarked;
import org.chromium.build.annotations.Nullable;
import org.chromium.ui.base.WindowAndroid;
/**
@ -19,6 +21,7 @@ import org.chromium.ui.base.WindowAndroid;
* to talk to the framework.
*/
@JNINamespace("printing")
@NullMarked
public class PrintingContext {
private static final String TAG = "Printing";
@ -92,7 +95,7 @@ public class PrintingContext {
}
@CalledByNative
public int[] getPages() {
public int @Nullable [] getPages() {
ThreadUtils.assertOnUiThread();
return mController.getPageNumbers();
}

@ -6,11 +6,15 @@ package org.chromium.printing;
import android.print.PrintDocumentAdapter;
import org.chromium.build.annotations.NullMarked;
import org.chromium.build.annotations.Nullable;
/**
* This interface describes a class which is responsible of talking to the printing backend.
*
* Such class communicates with a {@link PrintingContext}, which in turn talks to the native side.
*/
@NullMarked
public interface PrintingController {
/**
* @return Dots Per Inch (DPI) of the currently selected printer.
@ -37,7 +41,7 @@ public interface PrintingController {
* @return The individual page numbers of the document to be printed, of null if all pages are
* to be printed. The numbers are zero indexed.
*/
int[] getPageNumbers();
int @Nullable [] getPageNumbers();
/**
* @return If the controller is busy.

@ -4,6 +4,8 @@
package org.chromium.printing;
import static org.chromium.build.NullUtil.assumeNonNull;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.ParcelFileDescriptor;
@ -15,6 +17,8 @@ import androidx.annotation.VisibleForTesting;
import org.chromium.base.Log;
import org.chromium.base.ThreadUtils;
import org.chromium.build.annotations.NullMarked;
import org.chromium.build.annotations.Nullable;
import org.chromium.printing.PrintDocumentAdapterWrapper.PdfGenerator;
import java.io.IOException;
@ -29,6 +33,7 @@ import java.util.Iterator;
* the print button. The singleton object lives in UI thread. Interaction with the native side is
* carried through PrintingContext class.
*/
@NullMarked
public class PrintingControllerImpl implements PrintingController, PdfGenerator {
private static final String TAG = "printing";
@ -44,27 +49,27 @@ public class PrintingControllerImpl implements PrintingController, PdfGenerator
private static final int PRINTING_STATE_FINISHED = 2;
/** The singleton instance for this class. */
@VisibleForTesting protected static PrintingController sInstance;
@VisibleForTesting protected static @Nullable PrintingController sInstance;
private String mErrorMessage;
private @Nullable String mErrorMessage;
private int mRenderProcessId;
private int mRenderFrameId;
/** The file descriptor into which the PDF will be written. Provided by the framework. */
private ParcelFileDescriptor mFileDescriptor;
private @Nullable ParcelFileDescriptor mFileDescriptor;
/** Dots per inch, as provided by the framework. */
private int mDpi;
/** Paper dimensions. */
private PrintAttributes.MediaSize mMediaSize;
private PrintAttributes.@Nullable MediaSize mMediaSize;
/** Numbers of pages to be printed, zero indexed. */
private int[] mPages;
private int @Nullable [] mPages;
/** The callback function to inform the result of PDF generation to the framework. */
private PrintDocumentAdapterWrapper.WriteResultCallbackWrapper mOnWriteCallback;
private PrintDocumentAdapterWrapper.@Nullable WriteResultCallbackWrapper mOnWriteCallback;
/**
* The callback function to inform the result of layout to the framework. We save the callback
@ -72,10 +77,10 @@ public class PrintingControllerImpl implements PrintingController, PdfGenerator
* number of expected pages back to the framework through this callback once the native side
* has that information.
*/
private PrintDocumentAdapterWrapper.LayoutResultCallbackWrapper mOnLayoutCallback;
private PrintDocumentAdapterWrapper.@Nullable LayoutResultCallbackWrapper mOnLayoutCallback;
/** The object through which native PDF generation process is initiated. */
private Printable mPrintable;
private @Nullable Printable mPrintable;
/** The object through which the framework will make calls for generating PDF. */
private PrintDocumentAdapterWrapper mPrintDocumentAdapterWrapper;
@ -84,12 +89,11 @@ public class PrintingControllerImpl implements PrintingController, PdfGenerator
private boolean mIsBusy;
private PrintManagerDelegate mPrintManager;
private @Nullable PrintManagerDelegate mPrintManager;
@VisibleForTesting
protected PrintingControllerImpl() {
mPrintDocumentAdapterWrapper = new PrintDocumentAdapterWrapper();
mPrintDocumentAdapterWrapper.setPdfGenerator(this);
mPrintDocumentAdapterWrapper = new PrintDocumentAdapterWrapper(this);
}
/**
@ -118,21 +122,21 @@ public class PrintingControllerImpl implements PrintingController, PdfGenerator
@Override
public int getFileDescriptor() {
return mFileDescriptor.getFd();
return assumeNonNull(mFileDescriptor).getFd();
}
@Override
public int getPageHeight() {
return mMediaSize.getHeightMils();
return assumeNonNull(mMediaSize).getHeightMils();
}
@Override
public int getPageWidth() {
return mMediaSize.getWidthMils();
return assumeNonNull(mMediaSize).getWidthMils();
}
@Override
public int[] getPageNumbers() {
public int @Nullable [] getPageNumbers() {
return mPages == null ? null : mPages.clone();
}
@ -165,7 +169,7 @@ public class PrintingControllerImpl implements PrintingController, PdfGenerator
Log.d(TAG, "Pending print can't be started. PrintingController is busy.");
} else if (mPrintManager == null) {
Log.d(TAG, "Pending print can't be started. No PrintManager provided.");
} else if (!mPrintable.canPrint()) {
} else if (mPrintable == null || !mPrintable.canPrint()) {
Log.d(TAG, "Pending print can't be started. Printable can't perform printing.");
} else {
canStartPrint = true;
@ -174,6 +178,8 @@ public class PrintingControllerImpl implements PrintingController, PdfGenerator
if (!canStartPrint) return;
mIsBusy = true;
assert mPrintManager != null;
assert mPrintable != null;
mPrintDocumentAdapterWrapper.print(mPrintManager, mPrintable.getTitle());
mPrintManager = null;
}
@ -198,9 +204,9 @@ public class PrintingControllerImpl implements PrintingController, PdfGenerator
closeFileDescriptor();
if (pageCount > 0) {
PageRange[] pageRanges = convertIntegerArrayToPageRanges(mPages, pageCount);
mOnWriteCallback.onWriteFinished(pageRanges);
assumeNonNull(mOnWriteCallback).onWriteFinished(pageRanges);
} else {
mOnWriteCallback.onWriteFailed(mErrorMessage);
assumeNonNull(mOnWriteCallback).onWriteFailed(mErrorMessage);
resetCallbacks();
}
}
@ -216,10 +222,10 @@ public class PrintingControllerImpl implements PrintingController, PdfGenerator
PrintAttributes newAttributes,
CancellationSignal cancellationSignal,
PrintDocumentAdapterWrapper.LayoutResultCallbackWrapper callback,
Bundle metadata) {
@Nullable Bundle metadata) {
// NOTE: Chrome printing just supports one DPI, whereas Android has both vertical and
// horizontal. These two values are most of the time same, so we just pass one of them.
mDpi = newAttributes.getResolution().getHorizontalDpi();
mDpi = assumeNonNull(newAttributes.getResolution()).getHorizontalDpi();
mMediaSize = newAttributes.getMediaSize();
mOnLayoutCallback = callback;
@ -230,7 +236,7 @@ public class PrintingControllerImpl implements PrintingController, PdfGenerator
resetCallbacks();
} else {
PrintDocumentInfo info =
new PrintDocumentInfo.Builder(mPrintable.getTitle())
new PrintDocumentInfo.Builder(assumeNonNull(mPrintable).getTitle())
.setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
// Set page count to unknown since Android framework will get it from
// PDF file generated in onWrite.
@ -270,7 +276,7 @@ public class PrintingControllerImpl implements PrintingController, PdfGenerator
// mRenderProcessId and mRenderFrameId could be invalid values, in this case we are going to
// print the main frame.
if (mPrintable.print(mRenderProcessId, mRenderFrameId)) {
if (assumeNonNull(mPrintable).print(mRenderProcessId, mRenderFrameId)) {
mPrintingState = PRINTING_STATE_STARTED_FROM_ONWRITE;
} else {
mOnWriteCallback.onWriteFailed(mErrorMessage);
@ -314,7 +320,8 @@ public class PrintingControllerImpl implements PrintingController, PdfGenerator
}
}
private static PageRange[] convertIntegerArrayToPageRanges(int[] pagesArray, int pageCount) {
private static PageRange[] convertIntegerArrayToPageRanges(
int @Nullable [] pagesArray, int pageCount) {
PageRange[] pageRanges;
if (pagesArray != null) {
pageRanges = new PageRange[pagesArray.length];
@ -330,7 +337,7 @@ public class PrintingControllerImpl implements PrintingController, PdfGenerator
}
/** Gets an array of page ranges and returns an array of integers with all ranges expanded. */
private static int[] convertPageRangesToIntegerArray(final PageRange[] ranges) {
private static int @Nullable [] convertPageRangesToIntegerArray(final PageRange[] ranges) {
if (ranges.length == 1 && ranges[0].equals(PageRange.ALL_PAGES)) {
// null corresponds to all pages in Chromium printing logic.
return null;