1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.net.metrics;
18 
19 import android.net.MacAddress;
20 import android.os.Process;
21 import android.os.SystemClock;
22 import android.util.SparseIntArray;
23 
24 import java.util.StringJoiner;
25 
26 /**
27  * An event logged per interface and that aggregates WakeupEvents for that interface.
28  * {@hide}
29  */
30 public class WakeupStats {
31 
32     private static final int NO_UID = -1;
33 
34     public final long creationTimeMs = SystemClock.elapsedRealtime();
35     public final String iface;
36 
37     public long totalWakeups = 0;
38     public long rootWakeups = 0;
39     public long systemWakeups = 0;
40     public long nonApplicationWakeups = 0;
41     public long applicationWakeups = 0;
42     public long noUidWakeups = 0;
43     public long durationSec = 0;
44 
45     public long l2UnicastCount = 0;
46     public long l2MulticastCount = 0;
47     public long l2BroadcastCount = 0;
48 
49     public final SparseIntArray ethertypes = new SparseIntArray();
50     public final SparseIntArray ipNextHeaders = new SparseIntArray();
51 
WakeupStats(String iface)52     public WakeupStats(String iface) {
53         this.iface = iface;
54     }
55 
56     /** Update durationSec with current time. */
updateDuration()57     public void updateDuration() {
58         durationSec = (SystemClock.elapsedRealtime() - creationTimeMs) / 1000;
59     }
60 
61     /** Update wakeup counters for the given WakeupEvent. */
countEvent(WakeupEvent ev)62     public void countEvent(WakeupEvent ev) {
63         totalWakeups++;
64         switch (ev.uid) {
65             case Process.ROOT_UID:
66                 rootWakeups++;
67                 break;
68             case Process.SYSTEM_UID:
69                 systemWakeups++;
70                 break;
71             case NO_UID:
72                 noUidWakeups++;
73                 break;
74             default:
75                 if (ev.uid >= Process.FIRST_APPLICATION_UID) {
76                     applicationWakeups++;
77                 } else {
78                     nonApplicationWakeups++;
79                 }
80                 break;
81         }
82 
83         switch (ev.dstHwAddr.getAddressType()) {
84             case MacAddress.TYPE_UNICAST:
85                 l2UnicastCount++;
86                 break;
87             case MacAddress.TYPE_MULTICAST:
88                 l2MulticastCount++;
89                 break;
90             case MacAddress.TYPE_BROADCAST:
91                 l2BroadcastCount++;
92                 break;
93             default:
94                 break;
95         }
96 
97         increment(ethertypes, ev.ethertype);
98         if (ev.ipNextHeader >= 0) {
99             increment(ipNextHeaders, ev.ipNextHeader);
100         }
101     }
102 
103     @Override
toString()104     public String toString() {
105         updateDuration();
106         StringJoiner j = new StringJoiner(", ", "WakeupStats(", ")");
107         j.add(iface);
108         j.add("" + durationSec + "s");
109         j.add("total: " + totalWakeups);
110         j.add("root: " + rootWakeups);
111         j.add("system: " + systemWakeups);
112         j.add("apps: " + applicationWakeups);
113         j.add("non-apps: " + nonApplicationWakeups);
114         j.add("no uid: " + noUidWakeups);
115         j.add(String.format("l2 unicast/multicast/broadcast: %d/%d/%d",
116                 l2UnicastCount, l2MulticastCount, l2BroadcastCount));
117         for (int i = 0; i < ethertypes.size(); i++) {
118             int eth = ethertypes.keyAt(i);
119             int count = ethertypes.valueAt(i);
120             j.add(String.format("ethertype 0x%x: %d", eth, count));
121         }
122         for (int i = 0; i < ipNextHeaders.size(); i++) {
123             int proto = ipNextHeaders.keyAt(i);
124             int count = ipNextHeaders.valueAt(i);
125             j.add(String.format("ipNxtHdr %d: %d", proto, count));
126         }
127         return j.toString();
128     }
129 
increment(SparseIntArray counters, int key)130     private static void increment(SparseIntArray counters, int key) {
131         int newcount = counters.get(key, 0) + 1;
132         counters.put(key, newcount);
133     }
134 }
135