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