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 package com.android.server.net;
17 
18 import static android.net.ConnectivityManager.BLOCKED_REASON_NONE;
19 import static android.net.ConnectivityManager.FIREWALL_CHAIN_BACKGROUND;
20 import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
21 import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
22 import static android.net.ConnectivityManager.FIREWALL_CHAIN_METERED_ALLOW;
23 import static android.net.ConnectivityManager.FIREWALL_CHAIN_METERED_DENY_ADMIN;
24 import static android.net.ConnectivityManager.FIREWALL_CHAIN_METERED_DENY_USER;
25 import static android.net.ConnectivityManager.FIREWALL_CHAIN_POWERSAVE;
26 import static android.net.ConnectivityManager.FIREWALL_CHAIN_RESTRICTED;
27 import static android.net.ConnectivityManager.FIREWALL_CHAIN_STANDBY;
28 import static android.net.INetd.FIREWALL_RULE_ALLOW;
29 import static android.net.INetd.FIREWALL_RULE_DENY;
30 import static android.net.NetworkPolicyManager.ALLOWED_REASON_NONE;
31 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_BACKGROUND;
32 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
33 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_LOW_POWER_STANDBY;
34 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_METERED_ALLOW;
35 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_METERED_DENY_ADMIN;
36 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_METERED_DENY_USER;
37 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
38 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_RESTRICTED;
39 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
40 import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
41 import static android.os.PowerExemptionManager.reasonCodeToString;
42 import static android.os.Process.INVALID_UID;
43 
44 import android.annotation.Nullable;
45 import android.app.ActivityManager;
46 import android.app.ActivityManager.ProcessCapability;
47 import android.net.NetworkPolicyManager;
48 import android.os.UserHandle;
49 import android.util.ArraySet;
50 import android.util.Log;
51 import android.util.Slog;
52 
53 import com.android.internal.util.IndentingPrintWriter;
54 import com.android.internal.util.RingBuffer;
55 import com.android.server.am.ProcessList;
56 import com.android.server.net.NetworkPolicyManagerService.UidBlockedState;
57 
58 import java.text.SimpleDateFormat;
59 import java.util.Arrays;
60 import java.util.Date;
61 import java.util.Set;
62 
63 public class NetworkPolicyLogger {
64     static final String TAG = "NetworkPolicy";
65 
66     static final boolean LOGD = Log.isLoggable(TAG, Log.DEBUG);
67     static final boolean LOGV = Log.isLoggable(TAG, Log.VERBOSE);
68 
69     private static final int MAX_LOG_SIZE =
70             ActivityManager.isLowRamDeviceStatic() ? 100 : 400;
71     private static final int MAX_NETWORK_BLOCKED_LOG_SIZE =
72             ActivityManager.isLowRamDeviceStatic() ? 100 : 400;
73 
74     private static final int EVENT_TYPE_GENERIC = 0;
75     private static final int EVENT_NETWORK_BLOCKED = 1;
76     private static final int EVENT_UID_STATE_CHANGED = 2;
77     private static final int EVENT_POLICIES_CHANGED = 3;
78     private static final int EVENT_METEREDNESS_CHANGED = 4;
79     private static final int EVENT_USER_STATE_REMOVED = 5;
80     private static final int EVENT_RESTRICT_BG_CHANGED = 6;
81     private static final int EVENT_DEVICE_IDLE_MODE_ENABLED = 7;
82     private static final int EVENT_APP_IDLE_STATE_CHANGED = 8;
83     private static final int EVENT_PAROLE_STATE_CHANGED = 9;
84     private static final int EVENT_TEMP_POWER_SAVE_WL_CHANGED = 10;
85     private static final int EVENT_UID_FIREWALL_RULE_CHANGED = 11;
86     private static final int EVENT_FIREWALL_CHAIN_ENABLED = 12;
87     private static final int EVENT_UPDATE_METERED_RESTRICTED_PKGS = 13;
88     private static final int EVENT_APP_IDLE_WL_CHANGED = 14;
89     private static final int EVENT_METERED_ALLOWLIST_CHANGED = 15;
90     private static final int EVENT_METERED_DENYLIST_CHANGED = 16;
91     private static final int EVENT_ROAMING_CHANGED = 17;
92     private static final int EVENT_INTERFACES_CHANGED = 18;
93 
94     private final LogBuffer mNetworkBlockedBuffer = new LogBuffer(MAX_NETWORK_BLOCKED_LOG_SIZE);
95     private final LogBuffer mUidStateChangeBuffer = new LogBuffer(MAX_LOG_SIZE);
96     private final LogBuffer mEventsBuffer = new LogBuffer(MAX_LOG_SIZE);
97 
98     private int mDebugUid = INVALID_UID;
99 
100     private final Object mLock = new Object();
101 
networkBlocked(int uid, @Nullable UidBlockedState uidBlockedState)102     void networkBlocked(int uid, @Nullable UidBlockedState uidBlockedState) {
103         synchronized (mLock) {
104             if (LOGD || uid == mDebugUid) {
105                 Slog.d(TAG, "Blocked state of " + uid + ": " + uidBlockedState);
106             }
107             if (uidBlockedState == null) {
108                 mNetworkBlockedBuffer.networkBlocked(uid, BLOCKED_REASON_NONE, ALLOWED_REASON_NONE,
109                         BLOCKED_REASON_NONE);
110             } else {
111                 mNetworkBlockedBuffer.networkBlocked(uid, uidBlockedState.blockedReasons,
112                         uidBlockedState.allowedReasons, uidBlockedState.effectiveBlockedReasons);
113             }
114         }
115     }
116 
uidStateChanged(int uid, int procState, long procStateSeq, @ProcessCapability int capability)117     void uidStateChanged(int uid, int procState, long procStateSeq,
118             @ProcessCapability int capability) {
119         synchronized (mLock) {
120             if (LOGV || uid == mDebugUid) {
121                 Slog.v(TAG, uid + " state changed to "
122                         + ProcessList.makeProcStateString(procState) + ",seq=" + procStateSeq
123                         + ",cap=" + ActivityManager.getCapabilitiesSummary(capability));
124             }
125             mUidStateChangeBuffer.uidStateChanged(uid, procState, procStateSeq, capability);
126         }
127     }
128 
event(String msg)129     void event(String msg) {
130         synchronized (mLock) {
131             if (LOGV) Slog.v(TAG, msg);
132             mEventsBuffer.event(msg);
133         }
134     }
135 
uidPolicyChanged(int uid, int oldPolicy, int newPolicy)136     void uidPolicyChanged(int uid, int oldPolicy, int newPolicy) {
137         synchronized (mLock) {
138             if (LOGV || uid == mDebugUid) {
139                 Slog.v(TAG,
140                         getPolicyChangedLog(uid, oldPolicy, newPolicy));
141             }
142             mEventsBuffer.uidPolicyChanged(uid, oldPolicy, newPolicy);
143         }
144     }
145 
meterednessChanged(int netId, boolean newMetered)146     void meterednessChanged(int netId, boolean newMetered) {
147         synchronized (mLock) {
148             if (LOGD || mDebugUid != INVALID_UID) {
149                 Slog.d(TAG,
150                         getMeterednessChangedLog(netId, newMetered));
151             }
152             mEventsBuffer.meterednessChanged(netId, newMetered);
153         }
154     }
155 
removingUserState(int userId)156     void removingUserState(int userId) {
157         synchronized (mLock) {
158             if (LOGD || mDebugUid != INVALID_UID) {
159                 Slog.d(TAG, getUserRemovedLog(userId));
160             }
161             mEventsBuffer.userRemoved(userId);
162         }
163     }
164 
restrictBackgroundChanged(boolean oldValue, boolean newValue)165     void restrictBackgroundChanged(boolean oldValue, boolean newValue) {
166         synchronized (mLock) {
167             if (LOGD || mDebugUid != INVALID_UID) {
168                 Slog.d(TAG,
169                         getRestrictBackgroundChangedLog(oldValue, newValue));
170             }
171             mEventsBuffer.restrictBackgroundChanged(oldValue, newValue);
172         }
173     }
174 
deviceIdleModeEnabled(boolean enabled)175     void deviceIdleModeEnabled(boolean enabled) {
176         synchronized (mLock) {
177             if (LOGD || mDebugUid != INVALID_UID) {
178                 Slog.d(TAG, getDeviceIdleModeEnabled(enabled));
179             }
180             mEventsBuffer.deviceIdleModeEnabled(enabled);
181         }
182     }
183 
appIdleStateChanged(int uid, boolean idle)184     void appIdleStateChanged(int uid, boolean idle) {
185         synchronized (mLock) {
186             if (LOGD || uid == mDebugUid) {
187                 Slog.d(TAG, getAppIdleChangedLog(uid, idle));
188             }
189             mEventsBuffer.appIdleStateChanged(uid, idle);
190         }
191     }
192 
appIdleWlChanged(int uid, boolean isWhitelisted)193     void appIdleWlChanged(int uid, boolean isWhitelisted) {
194         synchronized (mLock) {
195             if (LOGD || uid == mDebugUid) {
196                 Slog.d(TAG, getAppIdleWlChangedLog(uid, isWhitelisted));
197             }
198             mEventsBuffer.appIdleWlChanged(uid, isWhitelisted);
199         }
200     }
201 
paroleStateChanged(boolean paroleOn)202     void paroleStateChanged(boolean paroleOn) {
203         synchronized (mLock) {
204             if (LOGD || mDebugUid != INVALID_UID) {
205                 Slog.d(TAG, getParoleStateChanged(paroleOn));
206             }
207             mEventsBuffer.paroleStateChanged(paroleOn);
208         }
209     }
210 
tempPowerSaveWlChanged(int appId, boolean added, int reasonCode, String reason)211     void tempPowerSaveWlChanged(int appId, boolean added, int reasonCode, String reason) {
212         synchronized (mLock) {
213             if (LOGV || appId == UserHandle.getAppId(mDebugUid)) {
214                 Slog.v(TAG, getTempPowerSaveWlChangedLog(appId, added, reasonCode, reason));
215             }
216             mEventsBuffer.tempPowerSaveWlChanged(appId, added, reasonCode, reason);
217         }
218     }
219 
uidFirewallRuleChanged(int chain, int uid, int rule)220     void uidFirewallRuleChanged(int chain, int uid, int rule) {
221         synchronized (mLock) {
222             if (LOGV || uid == mDebugUid) {
223                 Slog.v(TAG,
224                         getUidFirewallRuleChangedLog(chain, uid, rule));
225             }
226             mEventsBuffer.uidFirewallRuleChanged(chain, uid, rule);
227         }
228     }
229 
firewallChainEnabled(int chain, boolean enabled)230     void firewallChainEnabled(int chain, boolean enabled) {
231         synchronized (mLock) {
232             if (LOGD || mDebugUid != INVALID_UID) {
233                 Slog.d(TAG,
234                         getFirewallChainEnabledLog(chain, enabled));
235             }
236             mEventsBuffer.firewallChainEnabled(chain, enabled);
237         }
238     }
239 
firewallRulesChanged(int chain, int[] uids, int[] rules)240     void firewallRulesChanged(int chain, int[] uids, int[] rules) {
241         synchronized (mLock) {
242             final String log = "Firewall rules changed for " + getFirewallChainName(chain)
243                     + "; uids=" + Arrays.toString(uids) + "; rules=" + Arrays.toString(rules);
244             if (LOGD || mDebugUid != INVALID_UID) {
245                 Slog.d(TAG, log);
246             }
247             mEventsBuffer.event(log);
248         }
249     }
250 
meteredRestrictedPkgsChanged(Set<Integer> restrictedUids)251     void meteredRestrictedPkgsChanged(Set<Integer> restrictedUids) {
252         synchronized (mLock) {
253             final String log = "Metered restricted uids: " + restrictedUids;
254             if (LOGD || mDebugUid != INVALID_UID) {
255                 Slog.d(TAG, log);
256             }
257             mEventsBuffer.event(log);
258         }
259     }
260 
meteredAllowlistChanged(int uid, boolean added)261     void meteredAllowlistChanged(int uid, boolean added) {
262         synchronized (mLock) {
263             if (LOGD || mDebugUid == uid) {
264                 Slog.d(TAG, getMeteredAllowlistChangedLog(uid, added));
265             }
266             mEventsBuffer.meteredAllowlistChanged(uid, added);
267         }
268     }
269 
meteredDenylistChanged(int uid, boolean added)270     void meteredDenylistChanged(int uid, boolean added) {
271         synchronized (mLock) {
272             if (LOGD || mDebugUid == uid) {
273                 Slog.d(TAG, getMeteredDenylistChangedLog(uid, added));
274             }
275             mEventsBuffer.meteredDenylistChanged(uid, added);
276         }
277     }
278 
roamingChanged(int netId, boolean newRoaming)279     void roamingChanged(int netId, boolean newRoaming) {
280         synchronized (mLock) {
281             if (LOGD || mDebugUid != INVALID_UID) {
282                 Slog.d(TAG, getRoamingChangedLog(netId, newRoaming));
283             }
284             mEventsBuffer.roamingChanged(netId, newRoaming);
285         }
286     }
287 
interfacesChanged(int netId, ArraySet<String> newIfaces)288     void interfacesChanged(int netId, ArraySet<String> newIfaces) {
289         synchronized (mLock) {
290             if (LOGD || mDebugUid != INVALID_UID) {
291                 Slog.d(TAG, getInterfacesChangedLog(netId, newIfaces.toString()));
292             }
293             mEventsBuffer.interfacesChanged(netId, newIfaces.toString());
294         }
295     }
296 
setDebugUid(int uid)297     void setDebugUid(int uid) {
298         mDebugUid = uid;
299     }
300 
dumpLogs(IndentingPrintWriter pw)301     void dumpLogs(IndentingPrintWriter pw) {
302         synchronized (mLock) {
303             pw.println();
304             pw.println("mEventLogs (most recent first):");
305             pw.increaseIndent();
306             mEventsBuffer.reverseDump(pw);
307             pw.decreaseIndent();
308 
309             pw.println();
310             pw.println("mNetworkBlockedLogs (most recent first):");
311             pw.increaseIndent();
312             mNetworkBlockedBuffer.reverseDump(pw);
313             pw.decreaseIndent();
314 
315             pw.println();
316             pw.println("mUidStateChangeLogs (most recent first):");
317             pw.increaseIndent();
318             mUidStateChangeBuffer.reverseDump(pw);
319             pw.decreaseIndent();
320         }
321     }
322 
getPolicyChangedLog(int uid, int oldPolicy, int newPolicy)323     private static String getPolicyChangedLog(int uid, int oldPolicy, int newPolicy) {
324         return "Policy for " + uid + " changed from "
325                 + NetworkPolicyManager.uidPoliciesToString(oldPolicy) + " to "
326                 + NetworkPolicyManager.uidPoliciesToString(newPolicy);
327     }
328 
getMeterednessChangedLog(int netId, boolean newMetered)329     private static String getMeterednessChangedLog(int netId, boolean newMetered) {
330         return "Meteredness of netId=" + netId + " changed to " + newMetered;
331     }
332 
getUserRemovedLog(int userId)333     private static String getUserRemovedLog(int userId) {
334         return "Remove state for u" + userId;
335     }
336 
getRestrictBackgroundChangedLog(boolean oldValue, boolean newValue)337     private static String getRestrictBackgroundChangedLog(boolean oldValue, boolean newValue) {
338         return "Changed restrictBackground: " + oldValue + "->" + newValue;
339     }
340 
getDeviceIdleModeEnabled(boolean enabled)341     private static String getDeviceIdleModeEnabled(boolean enabled) {
342         return "DeviceIdleMode enabled: " + enabled;
343     }
344 
getAppIdleChangedLog(int uid, boolean idle)345     private static String getAppIdleChangedLog(int uid, boolean idle) {
346         return "App idle state of uid " + uid + ": " + idle;
347     }
348 
getAppIdleWlChangedLog(int uid, boolean isAllowlisted)349     private static String getAppIdleWlChangedLog(int uid, boolean isAllowlisted) {
350         return "App idle whitelist state of uid " + uid + ": " + isAllowlisted;
351     }
352 
getParoleStateChanged(boolean paroleOn)353     private static String getParoleStateChanged(boolean paroleOn) {
354         return "Parole state: " + paroleOn;
355     }
356 
getTempPowerSaveWlChangedLog(int appId, boolean added, int reasonCode, String reason)357     private static String getTempPowerSaveWlChangedLog(int appId, boolean added,
358             int reasonCode, String reason) {
359         return "temp-power-save whitelist for " + appId + " changed to: " + added
360                 + "; reason=" + reasonCodeToString(reasonCode) + " <" + reason + ">";
361     }
362 
getUidFirewallRuleChangedLog(int chain, int uid, int rule)363     private static String getUidFirewallRuleChangedLog(int chain, int uid, int rule) {
364         return String.format("Firewall rule changed: %d-%s-%s",
365                 uid, getFirewallChainName(chain), getFirewallRuleName(rule));
366     }
367 
getFirewallChainEnabledLog(int chain, boolean enabled)368     private static String getFirewallChainEnabledLog(int chain, boolean enabled) {
369         return "Firewall chain " + getFirewallChainName(chain) + " state: " + enabled;
370     }
371 
getMeteredAllowlistChangedLog(int uid, boolean added)372     private static String getMeteredAllowlistChangedLog(int uid, boolean added) {
373         return "metered-allowlist for " + uid + " changed to " + added;
374     }
375 
getMeteredDenylistChangedLog(int uid, boolean added)376     private static String getMeteredDenylistChangedLog(int uid, boolean added) {
377         return "metered-denylist for " + uid + " changed to " + added;
378     }
379 
getRoamingChangedLog(int netId, boolean newRoaming)380     private static String getRoamingChangedLog(int netId, boolean newRoaming) {
381         return "Roaming of netId=" + netId + " changed to " + newRoaming;
382     }
383 
getInterfacesChangedLog(int netId, String newIfaces)384     private static String getInterfacesChangedLog(int netId, String newIfaces) {
385         return "Interfaces of netId=" + netId + " changed to " + newIfaces;
386     }
387 
getFirewallChainName(int chain)388     static String getFirewallChainName(int chain) {
389         switch (chain) {
390             case FIREWALL_CHAIN_DOZABLE:
391                 return FIREWALL_CHAIN_NAME_DOZABLE;
392             case FIREWALL_CHAIN_STANDBY:
393                 return FIREWALL_CHAIN_NAME_STANDBY;
394             case FIREWALL_CHAIN_POWERSAVE:
395                 return FIREWALL_CHAIN_NAME_POWERSAVE;
396             case FIREWALL_CHAIN_RESTRICTED:
397                 return FIREWALL_CHAIN_NAME_RESTRICTED;
398             case FIREWALL_CHAIN_LOW_POWER_STANDBY:
399                 return FIREWALL_CHAIN_NAME_LOW_POWER_STANDBY;
400             case FIREWALL_CHAIN_BACKGROUND:
401                 return FIREWALL_CHAIN_NAME_BACKGROUND;
402             case FIREWALL_CHAIN_METERED_ALLOW:
403                 return FIREWALL_CHAIN_NAME_METERED_ALLOW;
404             case FIREWALL_CHAIN_METERED_DENY_USER:
405                 return FIREWALL_CHAIN_NAME_METERED_DENY_USER;
406             case FIREWALL_CHAIN_METERED_DENY_ADMIN:
407                 return FIREWALL_CHAIN_NAME_METERED_DENY_ADMIN;
408             default:
409                 return String.valueOf(chain);
410         }
411     }
412 
getFirewallRuleName(int rule)413     private static String getFirewallRuleName(int rule) {
414         switch (rule) {
415             case FIREWALL_RULE_DEFAULT:
416                 return "default";
417             case FIREWALL_RULE_ALLOW:
418                 return "allow";
419             case FIREWALL_RULE_DENY:
420                 return "deny";
421             default:
422                 return String.valueOf(rule);
423         }
424     }
425 
426     private final static class LogBuffer extends RingBuffer<Data> {
427         private static final SimpleDateFormat sFormatter
428                 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss:SSS");
429         private static final Date sDate = new Date();
430 
LogBuffer(int capacity)431         public LogBuffer(int capacity) {
432             super(Data::new, Data[]::new, capacity);
433         }
434 
uidStateChanged(int uid, int procState, long procStateSeq, @ProcessCapability int capability)435         public void uidStateChanged(int uid, int procState, long procStateSeq,
436                 @ProcessCapability int capability) {
437             final Data data = getNextSlot();
438             if (data == null) return;
439 
440             data.reset();
441             data.type = EVENT_UID_STATE_CHANGED;
442             data.ifield1 = uid;
443             data.ifield2 = procState;
444             data.ifield3 = capability;
445             data.lfield1 = procStateSeq;
446             data.timeStamp = System.currentTimeMillis();
447         }
448 
event(String msg)449         public void event(String msg) {
450             final Data data = getNextSlot();
451             if (data == null) return;
452 
453             data.reset();
454             data.type = EVENT_TYPE_GENERIC;
455             data.sfield1 = msg;
456             data.timeStamp = System.currentTimeMillis();
457         }
458 
networkBlocked(int uid, int blockedReasons, int allowedReasons, int effectiveBlockedReasons)459         public void networkBlocked(int uid, int blockedReasons, int allowedReasons,
460                 int effectiveBlockedReasons) {
461             final Data data = getNextSlot();
462             if (data == null) return;
463 
464             data.reset();
465             data.type = EVENT_NETWORK_BLOCKED;
466             data.ifield1 = uid;
467             data.ifield2 = blockedReasons;
468             data.ifield3 = allowedReasons;
469             data.ifield4 = effectiveBlockedReasons;
470             data.timeStamp = System.currentTimeMillis();
471         }
472 
uidPolicyChanged(int uid, int oldPolicy, int newPolicy)473         public void uidPolicyChanged(int uid, int oldPolicy, int newPolicy) {
474             final Data data = getNextSlot();
475             if (data == null) return;
476 
477             data.reset();
478             data.type = EVENT_POLICIES_CHANGED;
479             data.ifield1 = uid;
480             data.ifield2 = oldPolicy;
481             data.ifield3 = newPolicy;
482             data.timeStamp = System.currentTimeMillis();
483         }
484 
meterednessChanged(int netId, boolean newMetered)485         public void meterednessChanged(int netId, boolean newMetered) {
486             final Data data = getNextSlot();
487             if (data == null) return;
488 
489             data.reset();
490             data.type = EVENT_METEREDNESS_CHANGED;
491             data.ifield1 = netId;
492             data.bfield1 = newMetered;
493             data.timeStamp = System.currentTimeMillis();
494         }
495 
userRemoved(int userId)496         public void userRemoved(int userId) {
497             final Data data = getNextSlot();
498             if (data == null) return;
499 
500             data.reset();
501             data.type = EVENT_USER_STATE_REMOVED;
502             data.ifield1 = userId;
503             data.timeStamp = System.currentTimeMillis();
504         }
505 
restrictBackgroundChanged(boolean oldValue, boolean newValue)506         public void restrictBackgroundChanged(boolean oldValue, boolean newValue) {
507             final Data data = getNextSlot();
508             if (data == null) return;
509 
510             data.reset();
511             data.type = EVENT_RESTRICT_BG_CHANGED;
512             data.bfield1 = oldValue;
513             data.bfield2 = newValue;
514             data.timeStamp = System.currentTimeMillis();
515         }
516 
deviceIdleModeEnabled(boolean enabled)517         public void deviceIdleModeEnabled(boolean enabled) {
518             final Data data = getNextSlot();
519             if (data == null) return;
520 
521             data.reset();
522             data.type = EVENT_DEVICE_IDLE_MODE_ENABLED;
523             data.bfield1 = enabled;
524             data.timeStamp = System.currentTimeMillis();
525         }
526 
appIdleStateChanged(int uid, boolean idle)527         public void appIdleStateChanged(int uid, boolean idle) {
528             final Data data = getNextSlot();
529             if (data == null) return;
530 
531             data.reset();
532             data.type = EVENT_APP_IDLE_STATE_CHANGED;
533             data.ifield1 = uid;
534             data.bfield1 = idle;
535             data.timeStamp = System.currentTimeMillis();
536         }
537 
appIdleWlChanged(int uid, boolean isAllowlisted)538         public void appIdleWlChanged(int uid, boolean isAllowlisted) {
539             final Data data = getNextSlot();
540             if (data == null) return;
541 
542             data.reset();
543             data.type = EVENT_APP_IDLE_WL_CHANGED;
544             data.ifield1 = uid;
545             data.bfield1 = isAllowlisted;
546             data.timeStamp = System.currentTimeMillis();
547         }
548 
paroleStateChanged(boolean paroleOn)549         public void paroleStateChanged(boolean paroleOn) {
550             final Data data = getNextSlot();
551             if (data == null) return;
552 
553             data.reset();
554             data.type = EVENT_PAROLE_STATE_CHANGED;
555             data.bfield1 = paroleOn;
556             data.timeStamp = System.currentTimeMillis();
557         }
558 
tempPowerSaveWlChanged(int appId, boolean added, int reasonCode, String reason)559         public void tempPowerSaveWlChanged(int appId, boolean added,
560                 int reasonCode, String reason) {
561             final Data data = getNextSlot();
562             if (data == null) return;
563 
564             data.reset();
565             data.type = EVENT_TEMP_POWER_SAVE_WL_CHANGED;
566             data.ifield1 = appId;
567             data.ifield2 = reasonCode;
568             data.bfield1 = added;
569             data.sfield1 = reason;
570             data.timeStamp = System.currentTimeMillis();
571         }
572 
uidFirewallRuleChanged(int chain, int uid, int rule)573         public void uidFirewallRuleChanged(int chain, int uid, int rule) {
574             final Data data = getNextSlot();
575             if (data == null) return;
576 
577             data.reset();
578             data.type = EVENT_UID_FIREWALL_RULE_CHANGED;
579             data.ifield1 = chain;
580             data.ifield2 = uid;
581             data.ifield3 = rule;
582             data.timeStamp = System.currentTimeMillis();
583         }
584 
firewallChainEnabled(int chain, boolean enabled)585         public void firewallChainEnabled(int chain, boolean enabled) {
586             final Data data = getNextSlot();
587             if (data == null) return;
588 
589             data.reset();
590             data.type = EVENT_FIREWALL_CHAIN_ENABLED;
591             data.ifield1 = chain;
592             data.bfield1 = enabled;
593             data.timeStamp = System.currentTimeMillis();
594         }
595 
meteredAllowlistChanged(int uid, boolean added)596         public void meteredAllowlistChanged(int uid, boolean added) {
597             final Data data = getNextSlot();
598             if (data == null) return;
599 
600             data.reset();
601             data.type = EVENT_METERED_ALLOWLIST_CHANGED;
602             data.ifield1 = uid;
603             data.bfield1 = added;
604             data.timeStamp = System.currentTimeMillis();
605         }
606 
meteredDenylistChanged(int uid, boolean added)607         public void meteredDenylistChanged(int uid, boolean added) {
608             final Data data = getNextSlot();
609             if (data == null) return;
610 
611             data.reset();
612             data.type = EVENT_METERED_DENYLIST_CHANGED;
613             data.ifield1 = uid;
614             data.bfield1 = added;
615             data.timeStamp = System.currentTimeMillis();
616         }
617 
roamingChanged(int netId, boolean newRoaming)618         public void roamingChanged(int netId, boolean newRoaming) {
619             final Data data = getNextSlot();
620             if (data == null) return;
621 
622             data.reset();
623             data.type = EVENT_ROAMING_CHANGED;
624             data.ifield1 = netId;
625             data.bfield1 = newRoaming;
626             data.timeStamp = System.currentTimeMillis();
627         }
628 
interfacesChanged(int netId, String newIfaces)629         public void interfacesChanged(int netId, String newIfaces) {
630             final Data data = getNextSlot();
631             if (data == null) return;
632 
633             data.reset();
634             data.type = EVENT_INTERFACES_CHANGED;
635             data.ifield1 = netId;
636             data.sfield1 = newIfaces;
637             data.timeStamp = System.currentTimeMillis();
638         }
639 
reverseDump(IndentingPrintWriter pw)640         public void reverseDump(IndentingPrintWriter pw) {
641             final Data[] allData = toArray();
642             for (int i = allData.length - 1; i >= 0; --i) {
643                 if (allData[i] == null) {
644                     pw.println("NULL");
645                     continue;
646                 }
647                 pw.print(formatDate(allData[i].timeStamp));
648                 pw.print(" - ");
649                 pw.println(getContent(allData[i]));
650             }
651         }
652 
getContent(Data data)653         public String getContent(Data data) {
654             switch (data.type) {
655                 case EVENT_TYPE_GENERIC:
656                     return data.sfield1;
657                 case EVENT_NETWORK_BLOCKED:
658                     return data.ifield1 + "-" + UidBlockedState.toString(
659                             data.ifield2, data.ifield3, data.ifield4);
660                 case EVENT_UID_STATE_CHANGED:
661                     return data.ifield1 + ":" + ProcessList.makeProcStateString(data.ifield2)
662                             + ":" + ActivityManager.getCapabilitiesSummary(data.ifield3)
663                             + ":" + data.lfield1;
664                 case EVENT_POLICIES_CHANGED:
665                     return getPolicyChangedLog(data.ifield1, data.ifield2, data.ifield3);
666                 case EVENT_METEREDNESS_CHANGED:
667                     return getMeterednessChangedLog(data.ifield1, data.bfield1);
668                 case EVENT_USER_STATE_REMOVED:
669                     return getUserRemovedLog(data.ifield1);
670                 case EVENT_RESTRICT_BG_CHANGED:
671                     return getRestrictBackgroundChangedLog(data.bfield1, data.bfield2);
672                 case EVENT_DEVICE_IDLE_MODE_ENABLED:
673                     return getDeviceIdleModeEnabled(data.bfield1);
674                 case EVENT_APP_IDLE_STATE_CHANGED:
675                     return getAppIdleChangedLog(data.ifield1, data.bfield1);
676                 case EVENT_APP_IDLE_WL_CHANGED:
677                     return getAppIdleWlChangedLog(data.ifield1, data.bfield1);
678                 case EVENT_PAROLE_STATE_CHANGED:
679                     return getParoleStateChanged(data.bfield1);
680                 case EVENT_TEMP_POWER_SAVE_WL_CHANGED:
681                     return getTempPowerSaveWlChangedLog(data.ifield1, data.bfield1,
682                             data.ifield2, data.sfield1);
683                 case EVENT_UID_FIREWALL_RULE_CHANGED:
684                     return getUidFirewallRuleChangedLog(data.ifield1, data.ifield2, data.ifield3);
685                 case EVENT_FIREWALL_CHAIN_ENABLED:
686                     return getFirewallChainEnabledLog(data.ifield1, data.bfield1);
687                 case EVENT_METERED_ALLOWLIST_CHANGED:
688                     return getMeteredAllowlistChangedLog(data.ifield1, data.bfield1);
689                 case EVENT_METERED_DENYLIST_CHANGED:
690                     return getMeteredDenylistChangedLog(data.ifield1, data.bfield1);
691                 case EVENT_ROAMING_CHANGED:
692                     return getRoamingChangedLog(data.ifield1, data.bfield1);
693                 case EVENT_INTERFACES_CHANGED:
694                     return getInterfacesChangedLog(data.ifield1, data.sfield1);
695                 default:
696                     return String.valueOf(data.type);
697             }
698         }
699 
formatDate(long millis)700         private String formatDate(long millis) {
701             sDate.setTime(millis);
702             return sFormatter.format(sDate);
703         }
704     }
705 
706     /**
707      * Container class for all networkpolicy events data.
708      */
709     private static final class Data {
710         public int type;
711         public long timeStamp;
712 
713         public int ifield1;
714         public int ifield2;
715         public int ifield3;
716         public int ifield4;
717         public long lfield1;
718         public boolean bfield1;
719         public boolean bfield2;
720         public String sfield1;
721 
reset()722         public void reset(){
723             sfield1 = null;
724         }
725     }
726 }
727