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