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.INetd.FIREWALL_CHAIN_DOZABLE;
19 import static android.net.INetd.FIREWALL_CHAIN_POWERSAVE;
20 import static android.net.INetd.FIREWALL_CHAIN_STANDBY;
21 import static android.net.INetd.FIREWALL_RULE_ALLOW;
22 import static android.net.INetd.FIREWALL_RULE_DENY;
23 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
24 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
25 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
26 import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
27 
28 import android.app.ActivityManager;
29 import android.net.NetworkPolicyManager;
30 import android.util.Log;
31 import android.util.Slog;
32 
33 import com.android.internal.util.IndentingPrintWriter;
34 import com.android.internal.util.RingBuffer;
35 import com.android.server.am.ProcessList;
36 
37 import java.text.SimpleDateFormat;
38 import java.util.Arrays;
39 import java.util.Date;
40 import java.util.Set;
41 
42 public class NetworkPolicyLogger {
43     static final String TAG = "NetworkPolicy";
44 
45     static final boolean LOGD = Log.isLoggable(TAG, Log.DEBUG);
46     static final boolean LOGV = Log.isLoggable(TAG, Log.VERBOSE);
47 
48     private static final int MAX_LOG_SIZE =
49             ActivityManager.isLowRamDeviceStatic() ? 100 : 400;
50     private static final int MAX_NETWORK_BLOCKED_LOG_SIZE =
51             ActivityManager.isLowRamDeviceStatic() ? 100 : 400;
52 
53     private static final int EVENT_TYPE_GENERIC = 0;
54     private static final int EVENT_NETWORK_BLOCKED = 1;
55     private static final int EVENT_UID_STATE_CHANGED = 2;
56     private static final int EVENT_POLICIES_CHANGED = 3;
57     private static final int EVENT_METEREDNESS_CHANGED = 4;
58     private static final int EVENT_USER_STATE_REMOVED = 5;
59     private static final int EVENT_RESTRICT_BG_CHANGED = 6;
60     private static final int EVENT_DEVICE_IDLE_MODE_ENABLED = 7;
61     private static final int EVENT_APP_IDLE_STATE_CHANGED = 8;
62     private static final int EVENT_PAROLE_STATE_CHANGED = 9;
63     private static final int EVENT_TEMP_POWER_SAVE_WL_CHANGED = 10;
64     private static final int EVENT_UID_FIREWALL_RULE_CHANGED = 11;
65     private static final int EVENT_FIREWALL_CHAIN_ENABLED = 12;
66     private static final int EVENT_UPDATE_METERED_RESTRICTED_PKGS = 13;
67     private static final int EVENT_APP_IDLE_WL_CHANGED = 14;
68 
69     static final int NTWK_BLOCKED_POWER = 0;
70     static final int NTWK_ALLOWED_NON_METERED = 1;
71     static final int NTWK_BLOCKED_BLACKLIST = 2;
72     static final int NTWK_ALLOWED_WHITELIST = 3;
73     static final int NTWK_ALLOWED_TMP_WHITELIST = 4;
74     static final int NTWK_BLOCKED_BG_RESTRICT = 5;
75     static final int NTWK_ALLOWED_DEFAULT = 6;
76     static final int NTWK_ALLOWED_SYSTEM = 7;
77 
78     private final LogBuffer mNetworkBlockedBuffer = new LogBuffer(MAX_NETWORK_BLOCKED_LOG_SIZE);
79     private final LogBuffer mUidStateChangeBuffer = new LogBuffer(MAX_LOG_SIZE);
80     private final LogBuffer mEventsBuffer = new LogBuffer(MAX_LOG_SIZE);
81 
82     private final Object mLock = new Object();
83 
networkBlocked(int uid, int reason)84     void networkBlocked(int uid, int reason) {
85         synchronized (mLock) {
86             if (LOGD) Slog.d(TAG, uid + " is " + getBlockedReason(reason));
87             mNetworkBlockedBuffer.networkBlocked(uid, reason);
88         }
89     }
90 
uidStateChanged(int uid, int procState, long procStateSeq)91     void uidStateChanged(int uid, int procState, long procStateSeq) {
92         synchronized (mLock) {
93             if (LOGV) Slog.v(TAG,
94                     uid + " state changed to " + procState + " with seq=" + procStateSeq);
95             mUidStateChangeBuffer.uidStateChanged(uid, procState, procStateSeq);
96         }
97     }
98 
event(String msg)99     void event(String msg) {
100         synchronized (mLock) {
101             if (LOGV) Slog.v(TAG, msg);
102             mEventsBuffer.event(msg);
103         }
104     }
105 
uidPolicyChanged(int uid, int oldPolicy, int newPolicy)106     void uidPolicyChanged(int uid, int oldPolicy, int newPolicy) {
107         synchronized (mLock) {
108             if (LOGV) Slog.v(TAG, getPolicyChangedLog(uid, oldPolicy, newPolicy));
109             mEventsBuffer.uidPolicyChanged(uid, oldPolicy, newPolicy);
110         }
111     }
112 
meterednessChanged(int netId, boolean newMetered)113     void meterednessChanged(int netId, boolean newMetered) {
114         synchronized (mLock) {
115             if (LOGD) Slog.d(TAG, getMeterednessChangedLog(netId, newMetered));
116             mEventsBuffer.meterednessChanged(netId, newMetered);
117         }
118     }
119 
removingUserState(int userId)120     void removingUserState(int userId) {
121         synchronized (mLock) {
122             if (LOGD) Slog.d(TAG, getUserRemovedLog(userId));
123             mEventsBuffer.userRemoved(userId);
124         }
125     }
126 
restrictBackgroundChanged(boolean oldValue, boolean newValue)127     void restrictBackgroundChanged(boolean oldValue, boolean newValue) {
128         synchronized (mLock) {
129             if (LOGD) Slog.d(TAG,
130                     getRestrictBackgroundChangedLog(oldValue, newValue));
131             mEventsBuffer.restrictBackgroundChanged(oldValue, newValue);
132         }
133     }
134 
deviceIdleModeEnabled(boolean enabled)135     void deviceIdleModeEnabled(boolean enabled) {
136         synchronized (mLock) {
137             if (LOGD) Slog.d(TAG, getDeviceIdleModeEnabled(enabled));
138             mEventsBuffer.deviceIdleModeEnabled(enabled);
139         }
140     }
141 
appIdleStateChanged(int uid, boolean idle)142     void appIdleStateChanged(int uid, boolean idle) {
143         synchronized (mLock) {
144             if (LOGD) Slog.d(TAG, getAppIdleChangedLog(uid, idle));
145             mEventsBuffer.appIdleStateChanged(uid, idle);
146         }
147     }
148 
appIdleWlChanged(int uid, boolean isWhitelisted)149     void appIdleWlChanged(int uid, boolean isWhitelisted) {
150         synchronized (mLock) {
151             if (LOGD) Slog.d(TAG, getAppIdleWlChangedLog(uid, isWhitelisted));
152             mEventsBuffer.appIdleWlChanged(uid, isWhitelisted);
153         }
154     }
155 
paroleStateChanged(boolean paroleOn)156     void paroleStateChanged(boolean paroleOn) {
157         synchronized (mLock) {
158             if (LOGD) Slog.d(TAG, getParoleStateChanged(paroleOn));
159             mEventsBuffer.paroleStateChanged(paroleOn);
160         }
161     }
162 
tempPowerSaveWlChanged(int appId, boolean added)163     void tempPowerSaveWlChanged(int appId, boolean added) {
164         synchronized (mLock) {
165             if (LOGV) Slog.v(TAG, getTempPowerSaveWlChangedLog(appId, added));
166             mEventsBuffer.tempPowerSaveWlChanged(appId, added);
167         }
168     }
169 
uidFirewallRuleChanged(int chain, int uid, int rule)170     void uidFirewallRuleChanged(int chain, int uid, int rule) {
171         synchronized (mLock) {
172             if (LOGV) Slog.v(TAG, getUidFirewallRuleChangedLog(chain, uid, rule));
173             mEventsBuffer.uidFirewallRuleChanged(chain, uid, rule);
174         }
175     }
176 
firewallChainEnabled(int chain, boolean enabled)177     void firewallChainEnabled(int chain, boolean enabled) {
178         synchronized (mLock) {
179             if (LOGD) Slog.d(TAG, getFirewallChainEnabledLog(chain, enabled));
180             mEventsBuffer.firewallChainEnabled(chain, enabled);
181         }
182     }
183 
firewallRulesChanged(int chain, int[] uids, int[] rules)184     void firewallRulesChanged(int chain, int[] uids, int[] rules) {
185         synchronized (mLock) {
186             final String log = "Firewall rules changed for " + getFirewallChainName(chain)
187                     + "; uids=" + Arrays.toString(uids) + "; rules=" + Arrays.toString(rules);
188             if (LOGD) Slog.d(TAG, log);
189             mEventsBuffer.event(log);
190         }
191     }
192 
meteredRestrictedPkgsChanged(Set<Integer> restrictedUids)193     void meteredRestrictedPkgsChanged(Set<Integer> restrictedUids) {
194         synchronized (mLock) {
195             final String log = "Metered restricted uids: " + restrictedUids;
196             if (LOGD) Slog.d(TAG, log);
197             mEventsBuffer.event(log);
198         }
199     }
200 
dumpLogs(IndentingPrintWriter pw)201     void dumpLogs(IndentingPrintWriter pw) {
202         synchronized (mLock) {
203             pw.println();
204             pw.println("mEventLogs (most recent first):");
205             pw.increaseIndent();
206             mEventsBuffer.reverseDump(pw);
207             pw.decreaseIndent();
208 
209             pw.println();
210             pw.println("mNetworkBlockedLogs (most recent first):");
211             pw.increaseIndent();
212             mNetworkBlockedBuffer.reverseDump(pw);
213             pw.decreaseIndent();
214 
215             pw.println();
216             pw.println("mUidStateChangeLogs (most recent first):");
217             pw.increaseIndent();
218             mUidStateChangeBuffer.reverseDump(pw);
219             pw.decreaseIndent();
220         }
221     }
222 
getBlockedReason(int reason)223     private static String getBlockedReason(int reason) {
224         switch (reason) {
225             case NTWK_BLOCKED_POWER:
226                 return "blocked by power restrictions";
227             case NTWK_ALLOWED_NON_METERED:
228                 return "allowed on unmetered network";
229             case NTWK_BLOCKED_BLACKLIST:
230                 return "blacklisted on metered network";
231             case NTWK_ALLOWED_WHITELIST:
232                 return "whitelisted on metered network";
233             case NTWK_ALLOWED_TMP_WHITELIST:
234                 return "temporary whitelisted on metered network";
235             case NTWK_BLOCKED_BG_RESTRICT:
236                 return "blocked when background is restricted";
237             case NTWK_ALLOWED_DEFAULT:
238                 return "allowed by default";
239             default:
240                 return String.valueOf(reason);
241         }
242     }
243 
getPolicyChangedLog(int uid, int oldPolicy, int newPolicy)244     private static String getPolicyChangedLog(int uid, int oldPolicy, int newPolicy) {
245         return "Policy for " + uid + " changed from "
246                 + NetworkPolicyManager.uidPoliciesToString(oldPolicy) + " to "
247                 + NetworkPolicyManager.uidPoliciesToString(newPolicy);
248     }
249 
getMeterednessChangedLog(int netId, boolean newMetered)250     private static String getMeterednessChangedLog(int netId, boolean newMetered) {
251         return "Meteredness of netId=" + netId + " changed to " + newMetered;
252     }
253 
getUserRemovedLog(int userId)254     private static String getUserRemovedLog(int userId) {
255         return "Remove state for u" + userId;
256     }
257 
getRestrictBackgroundChangedLog(boolean oldValue, boolean newValue)258     private static String getRestrictBackgroundChangedLog(boolean oldValue, boolean newValue) {
259         return "Changed restrictBackground: " + oldValue + "->" + newValue;
260     }
261 
getDeviceIdleModeEnabled(boolean enabled)262     private static String getDeviceIdleModeEnabled(boolean enabled) {
263         return "DeviceIdleMode enabled: " + enabled;
264     }
265 
getAppIdleChangedLog(int uid, boolean idle)266     private static String getAppIdleChangedLog(int uid, boolean idle) {
267         return "App idle state of uid " + uid + ": " + idle;
268     }
269 
getAppIdleWlChangedLog(int uid, boolean isWhitelisted)270     private static String getAppIdleWlChangedLog(int uid, boolean isWhitelisted) {
271         return "App idle whitelist state of uid " + uid + ": " + isWhitelisted;
272     }
273 
getParoleStateChanged(boolean paroleOn)274     private static String getParoleStateChanged(boolean paroleOn) {
275         return "Parole state: " + paroleOn;
276     }
277 
getTempPowerSaveWlChangedLog(int appId, boolean added)278     private static String getTempPowerSaveWlChangedLog(int appId, boolean added) {
279         return "temp-power-save whitelist for " + appId + " changed to: " + added;
280     }
281 
getUidFirewallRuleChangedLog(int chain, int uid, int rule)282     private static String getUidFirewallRuleChangedLog(int chain, int uid, int rule) {
283         return String.format("Firewall rule changed: %d-%s-%s",
284                 uid, getFirewallChainName(chain), getFirewallRuleName(rule));
285     }
286 
getFirewallChainEnabledLog(int chain, boolean enabled)287     private static String getFirewallChainEnabledLog(int chain, boolean enabled) {
288         return "Firewall chain " + getFirewallChainName(chain) + " state: " + enabled;
289     }
290 
getFirewallChainName(int chain)291     private static String getFirewallChainName(int chain) {
292         switch (chain) {
293             case FIREWALL_CHAIN_DOZABLE:
294                 return FIREWALL_CHAIN_NAME_DOZABLE;
295             case FIREWALL_CHAIN_STANDBY:
296                 return FIREWALL_CHAIN_NAME_STANDBY;
297             case FIREWALL_CHAIN_POWERSAVE:
298                 return FIREWALL_CHAIN_NAME_POWERSAVE;
299             default:
300                 return String.valueOf(chain);
301         }
302     }
303 
getFirewallRuleName(int rule)304     private static String getFirewallRuleName(int rule) {
305         switch (rule) {
306             case FIREWALL_RULE_DEFAULT:
307                 return "default";
308             case FIREWALL_RULE_ALLOW:
309                 return "allow";
310             case FIREWALL_RULE_DENY:
311                 return "deny";
312             default:
313                 return String.valueOf(rule);
314         }
315     }
316 
317     private final static class LogBuffer extends RingBuffer<Data> {
318         private static final SimpleDateFormat sFormatter
319                 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss:SSS");
320         private static final Date sDate = new Date();
321 
LogBuffer(int capacity)322         public LogBuffer(int capacity) {
323             super(Data.class, capacity);
324         }
325 
uidStateChanged(int uid, int procState, long procStateSeq)326         public void uidStateChanged(int uid, int procState, long procStateSeq) {
327             final Data data = getNextSlot();
328             if (data == null) return;
329 
330             data.reset();
331             data.type = EVENT_UID_STATE_CHANGED;
332             data.ifield1 = uid;
333             data.ifield2 = procState;
334             data.lfield1 = procStateSeq;
335             data.timeStamp = System.currentTimeMillis();
336         }
337 
event(String msg)338         public void event(String msg) {
339             final Data data = getNextSlot();
340             if (data == null) return;
341 
342             data.reset();
343             data.type = EVENT_TYPE_GENERIC;
344             data.sfield1 = msg;
345             data.timeStamp = System.currentTimeMillis();
346         }
347 
networkBlocked(int uid, int reason)348         public void networkBlocked(int uid, int reason) {
349             final Data data = getNextSlot();
350             if (data == null) return;
351 
352             data.reset();
353             data.type = EVENT_NETWORK_BLOCKED;
354             data.ifield1 = uid;
355             data.ifield2 = reason;
356             data.timeStamp = System.currentTimeMillis();
357         }
358 
uidPolicyChanged(int uid, int oldPolicy, int newPolicy)359         public void uidPolicyChanged(int uid, int oldPolicy, int newPolicy) {
360             final Data data = getNextSlot();
361             if (data == null) return;
362 
363             data.reset();
364             data.type = EVENT_POLICIES_CHANGED;
365             data.ifield1 = uid;
366             data.ifield2 = oldPolicy;
367             data.ifield3 = newPolicy;
368             data.timeStamp = System.currentTimeMillis();
369         }
370 
meterednessChanged(int netId, boolean newMetered)371         public void meterednessChanged(int netId, boolean newMetered) {
372             final Data data = getNextSlot();
373             if (data == null) return;
374 
375             data.reset();
376             data.type = EVENT_METEREDNESS_CHANGED;
377             data.ifield1 = netId;
378             data.bfield1 = newMetered;
379             data.timeStamp = System.currentTimeMillis();
380         }
381 
userRemoved(int userId)382         public void userRemoved(int userId) {
383             final Data data = getNextSlot();
384             if (data == null) return;
385 
386             data.reset();
387             data.type = EVENT_USER_STATE_REMOVED;
388             data.ifield1 = userId;
389             data.timeStamp = System.currentTimeMillis();
390         }
391 
restrictBackgroundChanged(boolean oldValue, boolean newValue)392         public void restrictBackgroundChanged(boolean oldValue, boolean newValue) {
393             final Data data = getNextSlot();
394             if (data == null) return;
395 
396             data.reset();
397             data.type = EVENT_RESTRICT_BG_CHANGED;
398             data.bfield1 = oldValue;
399             data.bfield2 = newValue;
400             data.timeStamp = System.currentTimeMillis();
401         }
402 
deviceIdleModeEnabled(boolean enabled)403         public void deviceIdleModeEnabled(boolean enabled) {
404             final Data data = getNextSlot();
405             if (data == null) return;
406 
407             data.reset();
408             data.type = EVENT_DEVICE_IDLE_MODE_ENABLED;
409             data.bfield1 = enabled;
410             data.timeStamp = System.currentTimeMillis();
411         }
412 
appIdleStateChanged(int uid, boolean idle)413         public void appIdleStateChanged(int uid, boolean idle) {
414             final Data data = getNextSlot();
415             if (data == null) return;
416 
417             data.reset();
418             data.type = EVENT_APP_IDLE_STATE_CHANGED;
419             data.ifield1 = uid;
420             data.bfield1 = idle;
421             data.timeStamp = System.currentTimeMillis();
422         }
423 
appIdleWlChanged(int uid, boolean isWhitelisted)424         public void appIdleWlChanged(int uid, boolean isWhitelisted) {
425             final Data data = getNextSlot();
426             if (data == null) return;
427 
428             data.reset();
429             data.type = EVENT_APP_IDLE_WL_CHANGED;
430             data.ifield1 = uid;
431             data.bfield1 = isWhitelisted;
432             data.timeStamp = System.currentTimeMillis();
433         }
434 
paroleStateChanged(boolean paroleOn)435         public void paroleStateChanged(boolean paroleOn) {
436             final Data data = getNextSlot();
437             if (data == null) return;
438 
439             data.reset();
440             data.type = EVENT_PAROLE_STATE_CHANGED;
441             data.bfield1 = paroleOn;
442             data.timeStamp = System.currentTimeMillis();
443         }
444 
tempPowerSaveWlChanged(int appId, boolean added)445         public void tempPowerSaveWlChanged(int appId, boolean added) {
446             final Data data = getNextSlot();
447             if (data == null) return;
448 
449             data.reset();
450             data.type = EVENT_TEMP_POWER_SAVE_WL_CHANGED;
451             data.ifield1 = appId;
452             data.bfield1 = added;
453             data.timeStamp = System.currentTimeMillis();
454         }
455 
uidFirewallRuleChanged(int chain, int uid, int rule)456         public void uidFirewallRuleChanged(int chain, int uid, int rule) {
457             final Data data = getNextSlot();
458             if (data == null) return;
459 
460             data.reset();
461             data.type = EVENT_UID_FIREWALL_RULE_CHANGED;
462             data.ifield1 = chain;
463             data.ifield2 = uid;
464             data.ifield3 = rule;
465             data.timeStamp = System.currentTimeMillis();
466         }
467 
firewallChainEnabled(int chain, boolean enabled)468         public void firewallChainEnabled(int chain, boolean enabled) {
469             final Data data = getNextSlot();
470             if (data == null) return;
471 
472             data.reset();
473             data.type = EVENT_FIREWALL_CHAIN_ENABLED;
474             data.ifield1 = chain;
475             data.bfield1 = enabled;
476             data.timeStamp = System.currentTimeMillis();
477         }
478 
reverseDump(IndentingPrintWriter pw)479         public void reverseDump(IndentingPrintWriter pw) {
480             final Data[] allData = toArray();
481             for (int i = allData.length - 1; i >= 0; --i) {
482                 if (allData[i] == null) {
483                     pw.println("NULL");
484                     continue;
485                 }
486                 pw.print(formatDate(allData[i].timeStamp));
487                 pw.print(" - ");
488                 pw.println(getContent(allData[i]));
489             }
490         }
491 
getContent(Data data)492         public String getContent(Data data) {
493             switch (data.type) {
494                 case EVENT_TYPE_GENERIC:
495                     return data.sfield1;
496                 case EVENT_NETWORK_BLOCKED:
497                     return data.ifield1 + "-" + getBlockedReason(data.ifield2);
498                 case EVENT_UID_STATE_CHANGED:
499                     return data.ifield1 + "-" + ProcessList.makeProcStateString(data.ifield2)
500                             + "-" + data.lfield1;
501                 case EVENT_POLICIES_CHANGED:
502                     return getPolicyChangedLog(data.ifield1, data.ifield2, data.ifield3);
503                 case EVENT_METEREDNESS_CHANGED:
504                     return getMeterednessChangedLog(data.ifield1, data.bfield1);
505                 case EVENT_USER_STATE_REMOVED:
506                     return getUserRemovedLog(data.ifield1);
507                 case EVENT_RESTRICT_BG_CHANGED:
508                     return getRestrictBackgroundChangedLog(data.bfield1, data.bfield2);
509                 case EVENT_DEVICE_IDLE_MODE_ENABLED:
510                     return getDeviceIdleModeEnabled(data.bfield1);
511                 case EVENT_APP_IDLE_STATE_CHANGED:
512                     return getAppIdleChangedLog(data.ifield1, data.bfield1);
513                 case EVENT_APP_IDLE_WL_CHANGED:
514                     return getAppIdleWlChangedLog(data.ifield1, data.bfield1);
515                 case EVENT_PAROLE_STATE_CHANGED:
516                     return getParoleStateChanged(data.bfield1);
517                 case EVENT_TEMP_POWER_SAVE_WL_CHANGED:
518                     return getTempPowerSaveWlChangedLog(data.ifield1, data.bfield1);
519                 case EVENT_UID_FIREWALL_RULE_CHANGED:
520                     return getUidFirewallRuleChangedLog(data.ifield1, data.ifield2, data.ifield3);
521                 case EVENT_FIREWALL_CHAIN_ENABLED:
522                     return getFirewallChainEnabledLog(data.ifield1, data.bfield1);
523                 default:
524                     return String.valueOf(data.type);
525             }
526         }
527 
formatDate(long millis)528         private String formatDate(long millis) {
529             sDate.setTime(millis);
530             return sFormatter.format(sDate);
531         }
532     }
533 
534     public final static class Data {
535         int type;
536         long timeStamp;
537 
538         int ifield1;
539         int ifield2;
540         int ifield3;
541         long lfield1;
542         boolean bfield1;
543         boolean bfield2;
544         String sfield1;
545 
reset()546         public void reset(){
547             sfield1 = null;
548         }
549     }
550 }
551