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

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

Add event tracking to print UI.

Bug: 29391676
Change-Id: Iec09ac7296e50329e87268bcb70f5e60d566961c
parent 955f8ab4
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -161,6 +161,17 @@ public final class PrinterInfo implements Parcelable {
        return drawable;
    }

    /**
     * Check if the printer has a custom printer icon.
     *
     * @return {@code true} iff the printer has a custom printer icon.
     *
     * @hide
     */
    public boolean getHasCustomPrinterIcon() {
        return mHasCustomPrinterIcon;
    }

    /**
     * Get the printer name.
     *
+3 −1
Original line number Diff line number Diff line
@@ -89,6 +89,8 @@ public final class PrintSpoolerService extends Service {

    private static final boolean PERSISTENCE_MANAGER_ENABLED = true;

    private static final String PRINT_JOB_STATE_HISTO = "print_job_state";

    private static final long CHECK_ALL_PRINTJOBS_HANDLED_DELAY = 5000;

    private static final String PRINT_JOB_FILE_PREFIX = "print_job_";
@@ -532,7 +534,7 @@ public final class PrintSpoolerService extends Service {
                    Slog.i(LOG_TAG, "[STATE CHANGED] " + printJob);
                }

                MetricsLogger.histogram(this, "print_job_state", state);
                MetricsLogger.histogram(this, PRINT_JOB_STATE_HISTO, state);
                switch (state) {
                    case PrintJobInfo.STATE_COMPLETED:
                    case PrintJobInfo.STATE_CANCELED:
+16 −0
Original line number Diff line number Diff line
@@ -46,6 +46,8 @@ import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.printspooler.R;

import java.text.Collator;
@@ -123,6 +125,16 @@ public class AddPrinterActivity extends ListActivity implements AdapterView.OnIt
        getLoaderManager().initLoader(LOADER_ID_ALL_SERVICES, null, printServiceLoaderCallbacks);
    }

    @Override
    protected void onDestroy() {
        if (isFinishing()) {
            MetricsLogger.action(this, MetricsEvent.PRINT_ADD_PRINTERS,
                    mEnabledServicesAdapter.getCount());
        }

        super.onDestroy();
    }

    /**
     * Callbacks for the loaders operating on list of {@link PrintServiceInfo print service infos}.
     */
@@ -674,6 +686,10 @@ public class AddPrinterActivity extends ListActivity implements AdapterView.OnIt
            } else {
                RecommendationInfo recommendation = (RecommendationInfo) getItem(position);

                MetricsLogger.action(AddPrinterActivity.this,
                        MetricsEvent.ACTION_PRINT_RECOMMENDED_SERVICE_INSTALL,
                        recommendation.getPackageName().toString());

                try {
                    startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getString(
                            R.string.uri_package_details, recommendation.getPackageName()))));
+125 −8
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.printspooler.ui;

import android.annotation.NonNull;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
@@ -45,6 +46,8 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.print.IPrintDocumentAdapter;
import android.print.PageRange;
import android.print.PrintAttributes;
@@ -86,6 +89,7 @@ import android.widget.TextView;

import android.widget.Toast;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.printspooler.R;
import com.android.printspooler.model.MutexFileProvider;
import com.android.printspooler.model.PrintSpoolerProvider;
@@ -126,6 +130,11 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat

    private static final boolean DEBUG = false;

    // Constants for MetricsLogger.count and MetricsLogger.histo
    private static final String PRINT_PAGES_HISTO = "print_pages";
    private static final String PRINT_DEFAULT_COUNT = "print_default";
    private static final String PRINT_WORK_COUNT = "print_work";

    private static final String FRAGMENT_TAG = "FRAGMENT_TAG";

    private static final String HAS_PRINTED_PREF = "has_printed";
@@ -160,6 +169,14 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
    private static final int UI_STATE_ERROR = 1;
    private static final int UI_STATE_PROGRESS = 2;

    // see frameworks/base/proto/src/metrics_constats.proto -> ACTION_PRINT_JOB_OPTIONS
    private static final int PRINT_JOB_OPTIONS_SUBTYPE_COPIES = 1;
    private static final int PRINT_JOB_OPTIONS_SUBTYPE_COLOR_MODE = 2;
    private static final int PRINT_JOB_OPTIONS_SUBTYPE_DUPLEX_MODE = 3;
    private static final int PRINT_JOB_OPTIONS_SUBTYPE_MEDIA_SIZE = 4;
    private static final int PRINT_JOB_OPTIONS_SUBTYPE_ORIENTATION = 5;
    private static final int PRINT_JOB_OPTIONS_SUBTYPE_PAGE_RANGE = 6;

    private static final int MIN_COPIES = 1;
    private static final String MIN_COPIES_STRING = String.valueOf(MIN_COPIES);

@@ -228,6 +245,9 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat

    private int mUiState = UI_STATE_PREVIEW;

    /** The ID of the printer initially set */
    private PrinterId mDefaultPrinter;

    /** Observer for changes to the printers */
    private PrintersObserver mPrintersObserver;

@@ -263,6 +283,10 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat

        mCallingPackageName = extras.getString(DocumentsContract.EXTRA_PACKAGE_NAME);

        if (savedInstanceState == null) {
            MetricsLogger.action(this, MetricsEvent.PRINT_PREVIEW, mCallingPackageName);
        }

        // This will take just a few milliseconds, so just wait to
        // bind to the local service before showing the UI.
        mSpoolerProvider = new PrintSpoolerProvider(this,
@@ -354,7 +378,6 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
        if (mPrinterRegistry != null && mCurrentPrinter != null) {
            mPrinterRegistry.setTrackedPrinter(mCurrentPrinter.getId());
        }
        MetricsLogger.count(this, "print_preview", 1);
    }

    @Override
@@ -574,6 +597,7 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat

    @Override
    public void onOptionsOpened() {
        MetricsLogger.action(this, MetricsEvent.PRINT_JOB_OPTIONS);
        updateSelectedPagesFromPreview();
    }

@@ -677,6 +701,9 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
        if (resultCode == RESULT_OK && data != null) {
            updateOptionsUi();
            final Uri uri = data.getData();

            countPrintOperation(getPackageName());

            // Calling finish here does not invoke lifecycle callbacks but we
            // update the print job in onPause if finishing, hence post a message.
            mDestinationSpinner.post(new Runnable() {
@@ -725,6 +752,9 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
                mPrintJob.setPrinterName(printerInfo.getName());

                mDestinationSpinnerAdapter.ensurePrinterInVisibleAdapterPosition(printerInfo);

                MetricsLogger.action(this, MetricsEvent.ACTION_PRINTER_SELECT_ALL,
                        printerInfo.getId().getServiceName().getPackageName());
            }
        }

@@ -1044,12 +1074,35 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
        getFragmentManager().executePendingTransactions();
    }

    /**
     * Count that a print operation has been confirmed.
     *
     * @param packageName The package name of the print service used
     */
    private void countPrintOperation(@NonNull String packageName) {
        MetricsLogger.action(this, MetricsEvent.ACTION_PRINT, packageName);

        MetricsLogger.histogram(this, PRINT_PAGES_HISTO,
                getAdjustedPageCount(mPrintJob.getDocumentInfo()));

        if (mPrintJob.getPrinterId().equals(mDefaultPrinter)) {
            MetricsLogger.histogram(this, PRINT_DEFAULT_COUNT, 1);
        }

        UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
        if (um.isManagedProfile()) {
            MetricsLogger.histogram(this, PRINT_WORK_COUNT, 1);
        }
    }

    private void requestCreatePdfFileOrFinish() {
        mPrintedDocument.cancel(false);

        if (mCurrentPrinter == mDestinationSpinnerAdapter.getPdfPrinter()) {
            startCreateDocumentActivity();
        } else {
            countPrintOperation(mCurrentPrinter.getId().getServiceName().getPackageName());

            transformDocumentAndFinish(null);
        }
    }
@@ -1205,8 +1258,6 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
    private void confirmPrint() {
        setState(STATE_PRINT_CONFIRMED);

        MetricsLogger.count(this, "print_confirmed", 1);

        updateOptionsUi();
        addCurrentPrinterToHistory();
        setUserPrinted();
@@ -2677,11 +2728,14 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
                    return;
                }

                if (mDefaultPrinter == null) {
                    mDefaultPrinter = currentPrinter.getId();
                }

                PrinterId oldId = null;
                if (mCurrentPrinter != null) {
                    oldId = mCurrentPrinter.getId();
                }

                mCurrentPrinter = currentPrinter;

                if (oldId != null) {
@@ -2693,6 +2747,17 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
                        mDestinationSpinnerAdapter.notifyDataSetChanged();
                        return;
                    }

                    if (mState != STATE_INITIALIZING) {
                        if (currentPrinter != null) {
                            MetricsLogger.action(PrintActivity.this,
                                    MetricsEvent.ACTION_PRINTER_SELECT_DROPDOWN,
                                    currentPrinter.getId().getServiceName().getPackageName());
                        } else {
                            MetricsLogger.action(PrintActivity.this,
                                    MetricsEvent.ACTION_PRINTER_SELECT_DROPDOWN, "");
                        }
                    }
                }

                PrinterHolder printerHolder = mDestinationSpinnerAdapter.getPrinterHolder(
@@ -2729,24 +2794,57 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
                }

                if (newMediaSize != attributes.getMediaSize()) {
                    if (!newMediaSize.equals(attributes.getMediaSize())
                            && !attributes.getMediaSize().equals(MediaSize.UNKNOWN_LANDSCAPE)
                            && !attributes.getMediaSize().equals(MediaSize.UNKNOWN_PORTRAIT)
                            && mState != STATE_INITIALIZING) {
                        MetricsLogger.action(PrintActivity.this,
                                MetricsEvent.ACTION_PRINT_JOB_OPTIONS,
                                PRINT_JOB_OPTIONS_SUBTYPE_MEDIA_SIZE);
                    }

                    clearRanges = true;
                    attributes.setMediaSize(newMediaSize);
                }
            } else if (spinner == mColorModeSpinner) {
                SpinnerItem<Integer> colorModeItem = mColorModeSpinnerAdapter.getItem(position);
                mPrintJob.getAttributes().setColorMode(colorModeItem.value);
                int newMode = colorModeItem.value;

                if (mPrintJob.getAttributes().getColorMode() != newMode
                        && mState != STATE_INITIALIZING) {
                    MetricsLogger.action(PrintActivity.this, MetricsEvent.ACTION_PRINT_JOB_OPTIONS,
                            PRINT_JOB_OPTIONS_SUBTYPE_COLOR_MODE);
                }

                mPrintJob.getAttributes().setColorMode(newMode);
            } else if (spinner == mDuplexModeSpinner) {
                SpinnerItem<Integer> duplexModeItem = mDuplexModeSpinnerAdapter.getItem(position);
                mPrintJob.getAttributes().setDuplexMode(duplexModeItem.value);
                int newMode = duplexModeItem.value;

                if (mPrintJob.getAttributes().getDuplexMode() != newMode
                        && mState != STATE_INITIALIZING) {
                    MetricsLogger.action(PrintActivity.this, MetricsEvent.ACTION_PRINT_JOB_OPTIONS,
                            PRINT_JOB_OPTIONS_SUBTYPE_DUPLEX_MODE);
                }

                mPrintJob.getAttributes().setDuplexMode(newMode);
            } else if (spinner == mOrientationSpinner) {
                SpinnerItem<Integer> orientationItem = mOrientationSpinnerAdapter.getItem(position);
                PrintAttributes attributes = mPrintJob.getAttributes();

                if (mMediaSizeSpinner.getSelectedItem() != null) {
                    boolean isPortrait = attributes.isPortrait();
                    boolean newIsPortrait = orientationItem.value == ORIENTATION_PORTRAIT;

                    if (isPortrait != newIsPortrait) {
                        if (mState != STATE_INITIALIZING) {
                            MetricsLogger.action(PrintActivity.this,
                                    MetricsEvent.ACTION_PRINT_JOB_OPTIONS,
                                    PRINT_JOB_OPTIONS_SUBTYPE_ORIENTATION);
                        }

                    if (isPortrait != (orientationItem.value == ORIENTATION_PORTRAIT)) {
                        clearRanges = true;
                        if (orientationItem.value == ORIENTATION_PORTRAIT) {
                        if (newIsPortrait) {
                            attributes.copyFrom(attributes.asPortrait());
                        } else {
                            attributes.copyFrom(attributes.asLandscape());
@@ -2757,8 +2855,22 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
                if (mRangeOptionsSpinner.getSelectedItemPosition() == 0) {
                    clearRanges = true;
                    mPageRangeEditText.setText("");

                    if (mPageRangeEditText.getVisibility() == View.VISIBLE &&
                            mState != STATE_INITIALIZING) {
                        MetricsLogger.action(PrintActivity.this,
                                MetricsEvent.ACTION_PRINT_JOB_OPTIONS,
                                PRINT_JOB_OPTIONS_SUBTYPE_PAGE_RANGE);
                    }
                } else if (TextUtils.isEmpty(mPageRangeEditText.getText())) {
                    mPageRangeEditText.setError("");

                    if (mPageRangeEditText.getVisibility() != View.VISIBLE &&
                            mState != STATE_INITIALIZING) {
                        MetricsLogger.action(PrintActivity.this,
                                MetricsEvent.ACTION_PRINT_JOB_OPTIONS,
                                PRINT_JOB_OPTIONS_SUBTYPE_PAGE_RANGE);
                    }
                }
            }

@@ -2861,6 +2973,11 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
                /* ignore */
            }

            if (mState != STATE_INITIALIZING) {
                MetricsLogger.action(PrintActivity.this, MetricsEvent.ACTION_PRINT_JOB_OPTIONS,
                        PRINT_JOB_OPTIONS_SUBTYPE_COPIES);
            }

            if (copies < MIN_COPIES) {
                if (mCopiesEditText.getError() == null) {
                    mCopiesEditText.setError("");
+63 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.printspooler.ui;

import android.annotation.NonNull;
import android.app.Activity;
import android.app.LoaderManager;
import android.content.ComponentName;
@@ -56,6 +57,8 @@ import android.widget.SearchView;
import android.widget.TextView;
import android.widget.Toast;

import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.printspooler.R;

import java.util.ArrayList;
@@ -79,6 +82,12 @@ public final class SelectPrinterActivity extends Activity implements
    private static final String EXTRA_PRINTER_ID = "EXTRA_PRINTER_ID";

    private static final String KEY_NOT_FIRST_CREATE = "KEY_NOT_FIRST_CREATE";
    private static final String KEY_DID_SEARCH = "DID_SEARCH";

    // Constants for MetricsLogger.count and MetricsLogger.histo
    private static final String PRINTERS_LISTED_COUNT = "printers_listed";
    private static final String PRINTERS_ICON_COUNT = "printers_icon";
    private static final String PRINTERS_INFO_COUNT = "printers_info";

    /** The currently enabled print services by their ComponentName */
    private ArrayMap<ComponentName, PrintServiceInfo> mEnabledPrintServices;
@@ -89,7 +98,10 @@ public final class SelectPrinterActivity extends Activity implements

    private AnnounceFilterResult mAnnounceFilterResult;

    private boolean mDidSearch;

    private void startAddPrinterActivity() {
        MetricsLogger.action(this, MetricsEvent.ACTION_PRINT_SERVICE_ADD);
        startActivity(new Intent(this, AddPrinterActivity.class));
    }

@@ -185,12 +197,17 @@ public final class SelectPrinterActivity extends Activity implements
                }
            }
        }

        if (savedInstanceState != null) {
            mDidSearch = savedInstanceState.getBoolean(KEY_DID_SEARCH);
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putBoolean(KEY_NOT_FIRST_CREATE, true);
        outState.putBoolean(KEY_DID_SEARCH, mDidSearch);
    }

    @Override
@@ -305,6 +322,37 @@ public final class SelectPrinterActivity extends Activity implements
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        if (isFinishing()) {
            DestinationAdapter adapter = (DestinationAdapter) mListView.getAdapter();
            List<PrinterInfo> printers = adapter.getPrinters();
            int numPrinters = adapter.getPrinters().size();

            MetricsLogger.action(this, MetricsEvent.PRINT_ALL_PRINTERS, numPrinters);
            MetricsLogger.count(this, PRINTERS_LISTED_COUNT, numPrinters);

            int numInfoPrinters = 0;
            int numIconPrinters = 0;
            for (int i = 0; i < numPrinters; i++) {
                PrinterInfo printer = printers.get(i);

                if (printer.getInfoIntent() != null) {
                    numInfoPrinters++;
                }

                if (printer.getHasCustomPrinterIcon()) {
                    numIconPrinters++;
                }
            }

            MetricsLogger.count(this, PRINTERS_INFO_COUNT, numInfoPrinters);
            MetricsLogger.count(this, PRINTERS_ICON_COUNT, numIconPrinters);
        }

        super.onDestroy();
    }

    private void onPrinterSelected(PrinterInfo printer) {
        Intent intent = new Intent();
        intent.putExtra(INTENT_EXTRA_PRINTER, printer);
@@ -380,6 +428,15 @@ public final class SelectPrinterActivity extends Activity implements

        private CharSequence mLastSearchString;

        /**
         * Get the currently known printers.
         *
         * @return The currently known printers
         */
        @NonNull List<PrinterInfo> getPrinters() {
            return mPrinters;
        }

        public DestinationAdapter() {
            mPrinterRegistry.setOnPrintersChangeListener(new PrinterRegistry.OnPrintersChangeListener() {
                @Override
@@ -454,6 +511,12 @@ public final class SelectPrinterActivity extends Activity implements
                    if (resultCountChanged) {
                        announceSearchResultIfNeeded();
                    }

                    if (!mDidSearch) {
                        MetricsLogger.action(SelectPrinterActivity.this,
                                MetricsEvent.ACTION_PRINTER_SEARCH);
                        mDidSearch = true;
                    }
                    notifyDataSetChanged();
                }
            };
Loading