Guard against missing mac addresses in onWakeupEvent

The native code may not send any data for the NFULA_HWADDR on
some networks which can result in an exception. Logging an exception if
this happens over WiFi, as this is not expected.

Test: atest FrameworksNetTests
Test: Manually inspect logs and output of `dumpsys connmetrics`

Bug: 276498460
Change-Id: Iba20ec1f47b682cfff6127eeade0fdbf912945a6
Merged-In: Iba20ec1f47b682cfff6127eeade0fdbf912945a6
diff --git a/core/java/android/net/metrics/WakeupStats.java b/core/java/android/net/metrics/WakeupStats.java
index bb36536..fac747c 100644
--- a/core/java/android/net/metrics/WakeupStats.java
+++ b/core/java/android/net/metrics/WakeupStats.java
@@ -80,18 +80,20 @@
                 break;
         }
 
-        switch (ev.dstHwAddr.getAddressType()) {
-            case MacAddress.TYPE_UNICAST:
-                l2UnicastCount++;
-                break;
-            case MacAddress.TYPE_MULTICAST:
-                l2MulticastCount++;
-                break;
-            case MacAddress.TYPE_BROADCAST:
-                l2BroadcastCount++;
-                break;
-            default:
-                break;
+        if (ev.dstHwAddr != null) {
+            switch (ev.dstHwAddr.getAddressType()) {
+                case MacAddress.TYPE_UNICAST:
+                    l2UnicastCount++;
+                    break;
+                case MacAddress.TYPE_MULTICAST:
+                    l2MulticastCount++;
+                    break;
+                case MacAddress.TYPE_BROADCAST:
+                    l2BroadcastCount++;
+                    break;
+                default:
+                    break;
+            }
         }
 
         increment(ethertypes, ev.ethertype);
diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
index 1f82961..6d43061 100644
--- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
+++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
@@ -41,6 +41,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.BitUtils;
 import com.android.internal.util.FrameworkStatsLog;
 import com.android.internal.util.RingBuffer;
@@ -278,6 +279,11 @@
         }
     }
 
+    private boolean hasWifiTransport(Network network) {
+        final NetworkCapabilities nc = mCm.getNetworkCapabilities(network);
+        return nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
+    }
+
     @Override
     public synchronized void onWakeupEvent(String prefix, int uid, int ethertype, int ipNextHeader,
             byte[] dstHw, String srcIp, String dstIp, int srcPort, int dstPort, long timestampNs) {
@@ -286,12 +292,21 @@
             throw new IllegalArgumentException("Prefix " + prefix
                     + " required in format <nethandle>:<interface>");
         }
+        final long netHandle = Long.parseLong(prefixParts[0]);
+        final Network network = Network.fromNetworkHandle(netHandle);
 
         final WakeupEvent event = new WakeupEvent();
         event.iface = prefixParts[1];
         event.uid = uid;
         event.ethertype = ethertype;
-        event.dstHwAddr = MacAddress.fromBytes(dstHw);
+        if (ArrayUtils.isEmpty(dstHw)) {
+            if (hasWifiTransport(network)) {
+                Log.e(TAG, "Empty mac address on WiFi transport, network: " + network);
+            }
+            event.dstHwAddr = null;
+        } else {
+            event.dstHwAddr = MacAddress.fromBytes(dstHw);
+        }
         event.srcIp = srcIp;
         event.dstIp = dstIp;
         event.ipNextHeader = ipNextHeader;
@@ -306,14 +321,12 @@
 
         final BatteryStatsInternal bsi = LocalServices.getService(BatteryStatsInternal.class);
         if (bsi != null) {
-            final long netHandle = Long.parseLong(prefixParts[0]);
             final long elapsedMs = SystemClock.elapsedRealtime() + event.timestampMs
                     - System.currentTimeMillis();
-            bsi.noteCpuWakingNetworkPacket(Network.fromNetworkHandle(netHandle), elapsedMs,
-                    event.uid);
+            bsi.noteCpuWakingNetworkPacket(network, elapsedMs, event.uid);
         }
 
-        final String dstMac = event.dstHwAddr.toString();
+        final String dstMac = String.valueOf(event.dstHwAddr);
         FrameworkStatsLog.write(FrameworkStatsLog.PACKET_WAKEUP_OCCURRED,
                 uid, event.iface, ethertype, dstMac, srcIp, dstIp, ipNextHeader, srcPort, dstPort);
     }