stats: Add PrinterDiscovery event
We want to record what printer connections are available for setup.
Add the necessary enums and event recording logic with tests.
Bug: 390478410
Test: atest BuiltInPrintServiceRobolectricTest
Test: validate logged events via adb and webui
Flag: com.android.bips.flags.printing_telemetry
Change-Id: Iab6f6a862cd9769d12eedc3fdd9f101e8fd86718
diff --git a/src/com/android/bips/discovery/ManualDiscovery.java b/src/com/android/bips/discovery/ManualDiscovery.java
index 4b8f9a1..77147ba 100644
--- a/src/com/android/bips/discovery/ManualDiscovery.java
+++ b/src/com/android/bips/discovery/ManualDiscovery.java
@@ -22,8 +22,10 @@
import android.util.Log;
import com.android.bips.BuiltInPrintService;
+import com.android.bips.flags.Flags;
import com.android.bips.ipp.CapabilitiesCache;
import com.android.bips.jni.LocalPrinterCapabilities;
+import com.android.bips.stats.StatsAsyncLogger;
import com.android.bips.util.WifiMonitor;
import java.util.ArrayList;
@@ -220,6 +222,12 @@
}
mAddRequests.remove(this);
mFinalCallback.onFound(resolvedPrinter, capabilities.isSupported);
+ if (Flags.printingTelemetry()) {
+ StatsAsyncLogger.INSTANCE
+ .PrinterDiscovery(
+ StatsAsyncLogger.DiscoverySchemePrinterDiscoveryEvent.MANUAL,
+ resolvedPrinter.isSecure());
+ }
}
/** Stop all in-progress capability requests that are in progress */
diff --git a/src/com/android/bips/discovery/MdnsDiscovery.java b/src/com/android/bips/discovery/MdnsDiscovery.java
index 51c1781..3fe066f 100644
--- a/src/com/android/bips/discovery/MdnsDiscovery.java
+++ b/src/com/android/bips/discovery/MdnsDiscovery.java
@@ -25,6 +25,8 @@
import android.util.Log;
import com.android.bips.BuiltInPrintService;
+import com.android.bips.flags.Flags;
+import com.android.bips.stats.StatsAsyncLogger;
import java.net.Inet4Address;
import java.util.ArrayList;
@@ -116,7 +118,18 @@
+ "/" + resourcePath);
String location = getStringAttribute(info, ATTRIBUTE_NOTE);
- return new DiscoveredPrinter(uuidUri, info.getServiceName(), path, location);
+ if (Flags.printingTelemetry()) {
+ final DiscoveredPrinter discoveredPrinter = new DiscoveredPrinter(uuidUri,
+ info.getServiceName(),
+ path, location);
+ StatsAsyncLogger.INSTANCE
+ .PrinterDiscovery(
+ StatsAsyncLogger.DiscoverySchemePrinterDiscoveryEvent.MDNS,
+ discoveredPrinter.isSecure());
+ return discoveredPrinter;
+ } else {
+ return new DiscoveredPrinter(uuidUri, info.getServiceName(), path, location);
+ }
}
/** Return the value of an attribute or null if not present */
diff --git a/src/com/android/bips/p2p/P2pPrinterConnection.java b/src/com/android/bips/p2p/P2pPrinterConnection.java
index 7fd2be7..207941d 100644
--- a/src/com/android/bips/p2p/P2pPrinterConnection.java
+++ b/src/com/android/bips/p2p/P2pPrinterConnection.java
@@ -28,7 +28,9 @@
import com.android.bips.discovery.DiscoveredPrinter;
import com.android.bips.discovery.Discovery;
import com.android.bips.discovery.P2pDiscovery;
+import com.android.bips.flags.Flags;
import com.android.bips.jni.LocalPrinterCapabilities;
+import com.android.bips.stats.StatsAsyncLogger;
import java.net.Inet4Address;
import java.net.NetworkInterface;
@@ -68,6 +70,12 @@
if (DEBUG) Log.d(TAG, "Connecting to " + P2pMonitor.toString(peer));
// Initialize mPrinter to handle onPeerFound callback for re-discover cases
mPrinter = toPrinter(peer);
+ if (Flags.printingTelemetry()) {
+ StatsAsyncLogger.INSTANCE
+ .PrinterDiscovery(
+ StatsAsyncLogger.DiscoverySchemePrinterDiscoveryEvent.P2P,
+ mPrinter.isSecure());
+ }
connectToPeer(peer);
}
diff --git a/src/com/android/bips/stats/StatsAsyncLogger.kt b/src/com/android/bips/stats/StatsAsyncLogger.kt
index b87d8a5..cad9e8e 100644
--- a/src/com/android/bips/stats/StatsAsyncLogger.kt
+++ b/src/com/android/bips/stats/StatsAsyncLogger.kt
@@ -64,6 +64,41 @@
eventHandler = handler
}
+ fun PrinterDiscovery(
+ scheme: StatsAsyncLogger.DiscoverySchemePrinterDiscoveryEvent,
+ secure: Boolean,
+ ): Boolean {
+ if (DEBUG) {
+ Log.d(TAG, "Logging PrinterDiscovery event")
+ }
+ synchronized(semaphore) {
+ if (!semaphore.tryAcquire()) {
+ Log.w(TAG, "Logging too many events, dropping PrinterDiscovery event")
+ return false
+ }
+ val result =
+ eventHandler.postAtTime(
+ Runnable {
+ synchronized(semaphore) {
+ if (DEBUG) {
+ Log.d(TAG, "Async logging PrinterDiscovery event")
+ }
+ statsLogWrapper.internalPrinterDiscovery(scheme, secure)
+ semaphore.release()
+ }
+ },
+ nextAvailableTimeMillis,
+ )
+ if (!result) {
+ Log.e(TAG, "Could not log PrinterDiscovery event")
+ semaphore.release()
+ return false
+ }
+ nextAvailableTimeMillis = getNextAvailableTimeMillis()
+ }
+ return true
+ }
+
fun DiscoveredPrinterCapabilities(
makeAndModel: String,
colorModeMask: Int,
@@ -273,6 +308,28 @@
// Most of these are internal to the package so are prefixed with
// Internal
+ // PrinterDiscovery enums
+
+ // Not Internal because it is used by clients.
+ enum class DiscoverySchemePrinterDiscoveryEvent(val rawValue: Int) {
+ // Unspecified should never be used
+ UNSPECIFIED(
+ BipsStatsLog
+ .BIPS_PRINTER_DISCOVERY__DISCOVERY_SCHEME__BIPS_PRINTER_DISCOVERY_SCHEME_UNSPECIFIED
+ ),
+ MDNS(
+ BipsStatsLog
+ .BIPS_PRINTER_DISCOVERY__DISCOVERY_SCHEME__BIPS_PRINTER_DISCOVERY_SCHEME_MDNS
+ ),
+ MANUAL(
+ BipsStatsLog
+ .BIPS_PRINTER_DISCOVERY__DISCOVERY_SCHEME__BIPS_PRINTER_DISCOVERY_SCHEME_MANUAL
+ ),
+ P2P(
+ BipsStatsLog.BIPS_PRINTER_DISCOVERY__DISCOVERY_SCHEME__BIPS_PRINTER_DISCOVERY_SCHEME_P2P
+ ),
+ }
+
// DiscoveredPrinterCapabilities enums
enum class InternalMediaTypeDiscoveredPrinterCapsEvent(
diff --git a/src/com/android/bips/stats/StatsLogWrapper.kt b/src/com/android/bips/stats/StatsLogWrapper.kt
index 885594c..e8c45d5 100644
--- a/src/com/android/bips/stats/StatsLogWrapper.kt
+++ b/src/com/android/bips/stats/StatsLogWrapper.kt
@@ -37,6 +37,13 @@
)
}
+ open fun internalPrinterDiscovery(
+ scheme: StatsAsyncLogger.DiscoverySchemePrinterDiscoveryEvent,
+ secure: Boolean,
+ ) {
+ BipsStatsLog.write(BipsStatsLog.BIPS_PRINTER_DISCOVERY, scheme.rawValue, secure)
+ }
+
open fun internalDiscoveredPrinterCapabilities(
makeAndModel: String,
supportedColors: Set<StatsAsyncLogger.InternalColorModeDiscoveredPrinterCapsEvent>,
diff --git a/tests/robolectric/src/com/android/bips/stats/StatsAsyncLoggerTest.kt b/tests/robolectric/src/com/android/bips/stats/StatsAsyncLoggerTest.kt
index b9f1e97..53c4b09 100644
--- a/tests/robolectric/src/com/android/bips/stats/StatsAsyncLoggerTest.kt
+++ b/tests/robolectric/src/com/android/bips/stats/StatsAsyncLoggerTest.kt
@@ -61,6 +61,65 @@
}
@Test
+ fun printerDiscoverySuccessfullyLoggedTest() {
+ val logWrapperInOrder = inOrder(mStatsLogWrapper)
+ val handlerInOrder = inOrder(mHandler)
+ val semaphoreInOrder = inOrder(mSemaphore)
+ val timeCaptor = argumentCaptor<Long>()
+ val runnableCaptor = argumentCaptor<Runnable>()
+
+ // Arbitrary arguments
+ assertThat(
+ StatsAsyncLogger.PrinterDiscovery(
+ StatsAsyncLogger.DiscoverySchemePrinterDiscoveryEvent.MDNS,
+ false,
+ )
+ )
+ .isTrue()
+ assertThat(
+ StatsAsyncLogger.PrinterDiscovery(
+ StatsAsyncLogger.DiscoverySchemePrinterDiscoveryEvent.P2P,
+ true,
+ )
+ )
+ .isTrue()
+
+ handlerInOrder
+ .verify(mHandler, times(2))
+ .postAtTime(runnableCaptor.capture(), timeCaptor.capture())
+ handlerInOrder.verifyNoMoreInteractions()
+
+ // Validate delay args
+ val firstTime = timeCaptor.firstValue
+ val secondTime = timeCaptor.secondValue
+ assertThat(secondTime - firstTime)
+ .isAtLeast(StatsAsyncLogger.EVENT_REPORTED_MIN_INTERVAL.inWholeMilliseconds)
+ assertThat(secondTime - firstTime)
+ .isAtMost(2 * StatsAsyncLogger.EVENT_REPORTED_MIN_INTERVAL.inWholeMilliseconds)
+
+ // Validate Runnable logic
+ runnableCaptor.firstValue.run()
+ runnableCaptor.secondValue.run()
+ logWrapperInOrder
+ .verify(mStatsLogWrapper)
+ .internalPrinterDiscovery(
+ StatsAsyncLogger.DiscoverySchemePrinterDiscoveryEvent.MDNS,
+ false,
+ )
+ logWrapperInOrder
+ .verify(mStatsLogWrapper)
+ .internalPrinterDiscovery(
+ StatsAsyncLogger.DiscoverySchemePrinterDiscoveryEvent.P2P,
+ true,
+ )
+ logWrapperInOrder.verifyNoMoreInteractions()
+
+ // Validate Semaphore logic
+ semaphoreInOrder.verify(mSemaphore, times(2)).tryAcquire()
+ semaphoreInOrder.verify(mSemaphore, times(2)).release()
+ }
+
+ @Test
fun discoveredPrinterCapsSuccessfullyLoggedTest() {
val logWrapperInOrder = inOrder(mStatsLogWrapper)
val handlerInOrder = inOrder(mHandler)
@@ -355,6 +414,13 @@
)
)
.isFalse()
+ assertThat(
+ StatsAsyncLogger.PrinterDiscovery(
+ StatsAsyncLogger.DiscoverySchemePrinterDiscoveryEvent.MDNS,
+ false,
+ )
+ )
+ .isFalse()
verifyNoInteractions(mHandler)
}
@@ -381,7 +447,14 @@
StatsAsyncLogger.DiscoveredPrinterCapabilities("foo", 0, setOf(), 0, true, setOf())
)
.isFalse()
- verify(mSemaphore, times(3)).release()
+ assertThat(
+ StatsAsyncLogger.PrinterDiscovery(
+ StatsAsyncLogger.DiscoverySchemePrinterDiscoveryEvent.MDNS,
+ false,
+ )
+ )
+ .isFalse()
+ verify(mSemaphore, times(4)).release()
}
@Test