Home | History | Annotate | Download | only in net
      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.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE;
     19 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
     20 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
     21 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
     22 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_POWERSAVE;
     23 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_STANDBY;
     24 import static android.net.NetworkPolicyManager.FIREWALL_RULE_ALLOW;
     25 import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
     26 import static android.net.NetworkPolicyManager.FIREWALL_RULE_DENY;
     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() ? 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