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