1 /* 2 * Copyright (C) 2016 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 17 package com.android.server.wifi; 18 19 import android.annotation.NonNull; 20 import android.app.ActivityManager; 21 import android.content.Context; 22 import android.net.wifi.IWifiLowLatencyLockListener; 23 import android.net.wifi.WifiManager; 24 import android.os.BatteryStatsManager; 25 import android.os.Binder; 26 import android.os.Handler; 27 import android.os.IBinder; 28 import android.os.RemoteCallbackList; 29 import android.os.RemoteException; 30 import android.os.WorkSource; 31 import android.os.WorkSource.WorkChain; 32 import android.util.Log; 33 import android.util.Pair; 34 import android.util.SparseArray; 35 36 import com.android.internal.annotations.VisibleForTesting; 37 import com.android.modules.utils.build.SdkLevel; 38 import com.android.server.wifi.proto.WifiStatsLog; 39 import com.android.server.wifi.util.WifiPermissionsUtil; 40 import com.android.server.wifi.util.WorkSourceUtil; 41 import com.android.wifi.resources.R; 42 43 import java.io.PrintWriter; 44 import java.util.ArrayList; 45 import java.util.Arrays; 46 import java.util.List; 47 import java.util.NoSuchElementException; 48 import java.util.concurrent.Executor; 49 50 /** 51 * WifiLockManager maintains the list of wake locks held by different applications. 52 */ 53 public class WifiLockManager { 54 private static final String TAG = "WifiLockManager"; 55 56 private static final int LOW_LATENCY_SUPPORT_UNDEFINED = -1; 57 private static final int LOW_LATENCY_NOT_SUPPORTED = 0; 58 private static final int LOW_LATENCY_SUPPORTED = 1; 59 60 private static final int IGNORE_SCREEN_STATE_MASK = 0x01; 61 private static final int IGNORE_WIFI_STATE_MASK = 0x02; 62 63 private int mLatencyModeSupport = LOW_LATENCY_SUPPORT_UNDEFINED; 64 65 private boolean mVerboseLoggingEnabled = false; 66 67 private final Clock mClock; 68 private final Context mContext; 69 private final BatteryStatsManager mBatteryStats; 70 private final FrameworkFacade mFrameworkFacade; 71 private final ActiveModeWarden mActiveModeWarden; 72 private final ActivityManager mActivityManager; 73 private final Handler mHandler; 74 private final WifiMetrics mWifiMetrics; 75 76 private final List<WifiLock> mWifiLocks = new ArrayList<>(); 77 // map UIDs to their corresponding records (for low-latency locks) 78 private final SparseArray<UidRec> mLowLatencyUidWatchList = new SparseArray<>(); 79 /** the current op mode of the primary ClientModeManager */ 80 private int mCurrentOpMode = WifiManager.WIFI_MODE_NO_LOCKS_HELD; 81 private boolean mScreenOn = false; 82 /** whether Wifi is connected on the primary ClientModeManager */ 83 private boolean mWifiConnected = false; 84 85 // For shell command support 86 private boolean mForceHiPerfMode = false; 87 private boolean mForceLowLatencyMode = false; 88 89 // some wifi lock statistics 90 private int mFullHighPerfLocksAcquired; 91 private int mFullHighPerfLocksReleased; 92 private int mFullLowLatencyLocksAcquired; 93 private int mFullLowLatencyLocksReleased; 94 private long mCurrentSessionStartTimeMs; 95 private final DeviceConfigFacade mDeviceConfigFacade; 96 private final WifiPermissionsUtil mWifiPermissionsUtil; 97 private final RemoteCallbackList<IWifiLowLatencyLockListener> 98 mWifiLowLatencyLockListeners = new RemoteCallbackList<>(); 99 private boolean mIsLowLatencyActivated = false; 100 private WorkSource mLowLatencyBlamedWorkSource = new WorkSource(); 101 private WorkSource mHighPerfBlamedWorkSource = new WorkSource(); 102 private enum BlameReason { 103 WIFI_CONNECTION_STATE_CHANGED, 104 SCREEN_STATE_CHANGED, 105 }; 106 WifiLockManager( Context context, BatteryStatsManager batteryStats, ActiveModeWarden activeModeWarden, FrameworkFacade frameworkFacade, Handler handler, Clock clock, WifiMetrics wifiMetrics, DeviceConfigFacade deviceConfigFacade, WifiPermissionsUtil wifiPermissionsUtil, WifiDeviceStateChangeManager wifiDeviceStateChangeManager)107 WifiLockManager( 108 Context context, 109 BatteryStatsManager batteryStats, 110 ActiveModeWarden activeModeWarden, 111 FrameworkFacade frameworkFacade, 112 Handler handler, 113 Clock clock, 114 WifiMetrics wifiMetrics, 115 DeviceConfigFacade deviceConfigFacade, 116 WifiPermissionsUtil wifiPermissionsUtil, 117 WifiDeviceStateChangeManager wifiDeviceStateChangeManager) { 118 mContext = context; 119 mBatteryStats = batteryStats; 120 mActiveModeWarden = activeModeWarden; 121 mFrameworkFacade = frameworkFacade; 122 mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); 123 mHandler = handler; 124 mClock = clock; 125 mWifiMetrics = wifiMetrics; 126 mDeviceConfigFacade = deviceConfigFacade; 127 mWifiPermissionsUtil = wifiPermissionsUtil; 128 129 wifiDeviceStateChangeManager.registerStateChangeCallback( 130 new WifiDeviceStateChangeManager.StateChangeCallback() { 131 @Override 132 public void onScreenStateChanged(boolean screenOn) { 133 handleScreenStateChanged(screenOn); 134 } 135 }); 136 137 // Register for UID fg/bg transitions 138 registerUidImportanceTransitions(); 139 } 140 canDisableChipPowerSave()141 private boolean canDisableChipPowerSave() { 142 return mContext.getResources().getBoolean( 143 R.bool.config_wifiLowLatencyLockDisableChipPowerSave); 144 } 145 146 // Check for conditions to activate high-perf lock canActivateHighPerfLock(int ignoreMask)147 private boolean canActivateHighPerfLock(int ignoreMask) { 148 boolean check = true; 149 150 // Only condition is when Wifi is connected 151 if ((ignoreMask & IGNORE_WIFI_STATE_MASK) == 0) { 152 check = check && mWifiConnected; 153 } 154 155 return check; 156 } 157 canActivateHighPerfLock()158 private boolean canActivateHighPerfLock() { 159 return canActivateHighPerfLock(0); 160 } 161 162 // Check for conditions to activate low-latency lock canActivateLowLatencyLock(int ignoreMask, UidRec uidRec)163 private boolean canActivateLowLatencyLock(int ignoreMask, UidRec uidRec) { 164 boolean check = true; 165 166 if ((ignoreMask & IGNORE_WIFI_STATE_MASK) == 0) { 167 check = check && mWifiConnected; 168 } 169 if ((ignoreMask & IGNORE_SCREEN_STATE_MASK) == 0) { 170 check = check && mScreenOn; 171 } 172 if (uidRec != null) { 173 check = check && uidRec.mIsFg; 174 } 175 176 return check; 177 } 178 canActivateLowLatencyLock(int ignoreMask)179 private boolean canActivateLowLatencyLock(int ignoreMask) { 180 return canActivateLowLatencyLock(ignoreMask, null); 181 } 182 canActivateLowLatencyLock()183 private boolean canActivateLowLatencyLock() { 184 return canActivateLowLatencyLock(0, null); 185 } 186 onAppForeground(final int uid, final int importance)187 private void onAppForeground(final int uid, final int importance) { 188 mHandler.post(() -> { 189 UidRec uidRec = mLowLatencyUidWatchList.get(uid); 190 if (uidRec == null) { 191 // Not a uid in the watch list 192 return; 193 } 194 195 boolean newModeIsFg = isAppForeground(uid, importance); 196 if (uidRec.mIsFg == newModeIsFg) { 197 return; // already at correct state 198 } 199 200 uidRec.mIsFg = newModeIsFg; 201 updateOpMode(); 202 203 // If conditions for lock activation are met, 204 // then UID either share the blame, or removed from sharing 205 // whether to start or stop the blame based on UID fg/bg state 206 if (canActivateLowLatencyLock( 207 uidRec.mIsScreenOnExempted ? IGNORE_SCREEN_STATE_MASK : 0)) { 208 setBlameLowLatencyUid(uid, uidRec.mIsFg); 209 notifyLowLatencyActiveUsersChanged(); 210 } 211 }); 212 } 213 214 // Detect UIDs going, 215 // - Foreground <-> Background 216 // - Foreground service <-> Background registerUidImportanceTransitions()217 private void registerUidImportanceTransitions() { 218 mActivityManager.addOnUidImportanceListener(new ActivityManager.OnUidImportanceListener() { 219 @Override 220 public void onUidImportance(final int uid, final int importance) { 221 onAppForeground(uid, importance); 222 } 223 }, ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND); 224 mActivityManager.addOnUidImportanceListener(new ActivityManager.OnUidImportanceListener() { 225 @Override 226 public void onUidImportance(final int uid, final int importance) { 227 onAppForeground(uid, importance); 228 } 229 }, ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE); 230 } 231 232 /** 233 * Method allowing a calling app to acquire a Wifi WakeLock in the supplied mode. 234 * 235 * This method checks that the lock mode is a valid WifiLock mode. 236 * @param lockMode int representation of the Wifi WakeLock type. 237 * @param tag String passed to WifiManager.WifiLock 238 * @param binder IBinder for the calling app 239 * @param ws WorkSource of the calling app 240 * 241 * @return true if the lock was successfully acquired, false if the lockMode was invalid. 242 */ acquireWifiLock(int lockMode, String tag, IBinder binder, WorkSource ws)243 public boolean acquireWifiLock(int lockMode, String tag, IBinder binder, WorkSource ws) { 244 // Make a copy of the WorkSource before adding it to the WakeLock 245 // This is to make sure worksource value can not be changed by caller 246 // after function returns. 247 WorkSource newWorkSource = new WorkSource(ws); 248 // High perf lock is deprecated from Android U onwards. Acquisition of High perf lock 249 // will be treated as a call to Low Latency Lock. 250 if (mDeviceConfigFacade.isHighPerfLockDeprecated() && SdkLevel.isAtLeastU() 251 && lockMode == WifiManager.WIFI_MODE_FULL_HIGH_PERF) { 252 lockMode = WifiManager.WIFI_MODE_FULL_LOW_LATENCY; 253 } 254 return addLock(new WifiLock(lockMode, tag, binder, newWorkSource)); 255 } 256 257 /** 258 * Method used by applications to release a WiFi Wake lock. 259 * 260 * @param binder IBinder for the calling app. 261 * @return true if the lock was released, false if the caller did not hold any locks 262 */ releaseWifiLock(IBinder binder)263 public boolean releaseWifiLock(IBinder binder) { 264 return releaseLock(binder); 265 } 266 267 /** 268 * Method used to get the strongest lock type currently held by the WifiLockManager. 269 * 270 * If no locks are held, WifiManager.WIFI_MODE_NO_LOCKS_HELD is returned. 271 * 272 * @return int representing the currently held (highest power consumption) lock. 273 */ 274 @VisibleForTesting getStrongestLockMode()275 synchronized int getStrongestLockMode() { 276 // If Wifi Client is not connected, then all locks are not effective 277 if (!mWifiConnected) { 278 return WifiManager.WIFI_MODE_NO_LOCKS_HELD; 279 } 280 281 // Check if mode is forced to hi-perf 282 if (mForceHiPerfMode) { 283 return WifiManager.WIFI_MODE_FULL_HIGH_PERF; 284 } 285 286 // Check if mode is forced to low-latency 287 if (mForceLowLatencyMode) { 288 return WifiManager.WIFI_MODE_FULL_LOW_LATENCY; 289 } 290 291 if (mScreenOn && countFgLowLatencyUids(false) > 0) { 292 return WifiManager.WIFI_MODE_FULL_LOW_LATENCY; 293 } 294 295 if (!mScreenOn && countFgLowLatencyUids(true) > 0) { 296 return WifiManager.WIFI_MODE_FULL_LOW_LATENCY; 297 } 298 299 if (mFullHighPerfLocksAcquired > mFullHighPerfLocksReleased) { 300 return WifiManager.WIFI_MODE_FULL_HIGH_PERF; 301 } 302 303 return WifiManager.WIFI_MODE_NO_LOCKS_HELD; 304 } 305 306 /** 307 * Method to create a WorkSource containing all active WifiLock WorkSources. 308 */ createMergedWorkSource()309 public synchronized WorkSource createMergedWorkSource() { 310 WorkSource mergedWS = new WorkSource(); 311 for (WifiLock lock : mWifiLocks) { 312 mergedWS.add(lock.getWorkSource()); 313 } 314 return mergedWS; 315 } 316 317 /** 318 * Method used to update WifiLocks with a new WorkSouce. 319 * 320 * @param binder IBinder for the calling application. 321 * @param ws WorkSource to add to the existing WifiLock(s). 322 */ updateWifiLockWorkSource(IBinder binder, WorkSource ws)323 public synchronized void updateWifiLockWorkSource(IBinder binder, WorkSource ws) { 324 325 // Now check if there is an active lock 326 WifiLock wl = findLockByBinder(binder); 327 if (wl == null) { 328 throw new IllegalArgumentException("Wifi lock not active"); 329 } 330 331 // Make a copy of the WorkSource before adding it to the WakeLock 332 // This is to make sure worksource value can not be changed by caller 333 // after function returns. 334 WorkSource newWorkSource = new WorkSource(ws); 335 336 if (mVerboseLoggingEnabled) { 337 Log.d(TAG, "updateWifiLockWakeSource: " + wl + ", newWorkSource=" + newWorkSource); 338 } 339 340 // Note: 341 // Log the acquire before the release to avoid "holes" in the collected data due to 342 // an acquire event immediately after a release in the case where newWorkSource and 343 // wl.mWorkSource share one or more attribution UIDs. Both batteryStats and statsd 344 // can correctly match "nested" acquire / release pairs. 345 switch(wl.mMode) { 346 case WifiManager.WIFI_MODE_FULL_HIGH_PERF: 347 // Shift blame to new worksource if needed 348 if (canActivateHighPerfLock()) { 349 setBlameHiPerfWs(newWorkSource, true); 350 setBlameHiPerfWs(wl.mWorkSource, false); 351 } 352 break; 353 case WifiManager.WIFI_MODE_FULL_LOW_LATENCY: 354 addWsToLlWatchList(newWorkSource); 355 removeWsFromLlWatchList(wl.mWorkSource); 356 updateOpMode(); 357 break; 358 default: 359 // Do nothing 360 break; 361 } 362 363 wl.mWorkSource = newWorkSource; 364 } 365 366 /** 367 * Method Used for shell command support 368 * 369 * @param isEnabled True to force hi-perf mode, false to leave it up to acquired wifiLocks. 370 * @return True for success, false for failure (failure turns forcing mode off) 371 */ forceHiPerfMode(boolean isEnabled)372 public boolean forceHiPerfMode(boolean isEnabled) { 373 mForceHiPerfMode = isEnabled; 374 mForceLowLatencyMode = false; 375 if (!updateOpMode()) { 376 Log.e(TAG, "Failed to force hi-perf mode, returning to normal mode"); 377 mForceHiPerfMode = false; 378 return false; 379 } 380 return true; 381 } 382 383 /** 384 * Method Used for shell command support 385 * 386 * @param isEnabled True to force low-latency mode, false to leave it up to acquired wifiLocks. 387 * @return True for success, false for failure (failure turns forcing mode off) 388 */ forceLowLatencyMode(boolean isEnabled)389 public boolean forceLowLatencyMode(boolean isEnabled) { 390 mForceLowLatencyMode = isEnabled; 391 mForceHiPerfMode = false; 392 if (!updateOpMode()) { 393 Log.e(TAG, "Failed to force low-latency mode, returning to normal mode"); 394 mForceLowLatencyMode = false; 395 return false; 396 } 397 return true; 398 } 399 400 /** 401 * Handler for screen state (on/off) changes 402 */ handleScreenStateChanged(boolean screenOn)403 private void handleScreenStateChanged(boolean screenOn) { 404 if (mVerboseLoggingEnabled) { 405 Log.d(TAG, "handleScreenStateChanged: screenOn = " + screenOn); 406 } 407 408 mScreenOn = screenOn; 409 410 if (canActivateLowLatencyLock(IGNORE_SCREEN_STATE_MASK)) { 411 // Update the running mode 412 updateOpMode(); 413 // Adjust blaming for UIDs in foreground 414 setBlameLowLatencyWatchList(BlameReason.SCREEN_STATE_CHANGED, screenOn); 415 } 416 } 417 418 /** 419 * Handler for Wifi Client mode state changes 420 */ updateWifiClientConnected( ClientModeManager clientModeManager, boolean isConnected)421 public void updateWifiClientConnected( 422 ClientModeManager clientModeManager, boolean isConnected) { 423 boolean hasAtLeastOneConnection = isConnected 424 || mActiveModeWarden.getClientModeManagers().stream().anyMatch( 425 cmm -> cmm.isConnected()); 426 if (mVerboseLoggingEnabled) { 427 Log.d(TAG, "updateWifiClientConnected hasAtLeastOneConnection=" 428 + hasAtLeastOneConnection); 429 } 430 if (mWifiConnected == hasAtLeastOneConnection) { 431 // No need to take action 432 return; 433 } 434 mWifiConnected = hasAtLeastOneConnection; 435 436 // Adjust blaming for UIDs in foreground carrying low latency locks 437 if (canActivateLowLatencyLock(countFgLowLatencyUids(/*isScreenOnExempted*/ true) > 0 438 ? IGNORE_SCREEN_STATE_MASK | IGNORE_WIFI_STATE_MASK 439 : IGNORE_WIFI_STATE_MASK)) { 440 setBlameLowLatencyWatchList(BlameReason.WIFI_CONNECTION_STATE_CHANGED, mWifiConnected); 441 } 442 443 // Adjust blaming for UIDs carrying high perf locks 444 // Note that blaming is adjusted only if needed, 445 // since calling this API is reference counted 446 if (canActivateHighPerfLock(IGNORE_WIFI_STATE_MASK)) { 447 setBlameHiPerfLocks(mWifiConnected); 448 } 449 450 updateOpMode(); 451 } 452 setBlameHiPerfLocks(boolean shouldBlame)453 private synchronized void setBlameHiPerfLocks(boolean shouldBlame) { 454 for (WifiLock lock : mWifiLocks) { 455 if (lock.mMode == WifiManager.WIFI_MODE_FULL_HIGH_PERF) { 456 setBlameHiPerfWs(lock.getWorkSource(), shouldBlame); 457 } 458 } 459 } 460 461 /** 462 * Validate that the lock mode is valid - i.e. one of the supported enumerations. 463 * 464 * @param lockMode The lock mode to verify. 465 * @return true for valid lock modes, false otherwise. 466 */ isValidLockMode(int lockMode)467 public static boolean isValidLockMode(int lockMode) { 468 if (lockMode != WifiManager.WIFI_MODE_FULL 469 && lockMode != WifiManager.WIFI_MODE_SCAN_ONLY 470 && lockMode != WifiManager.WIFI_MODE_FULL_HIGH_PERF 471 && lockMode != WifiManager.WIFI_MODE_FULL_LOW_LATENCY) { 472 return false; 473 } 474 return true; 475 } 476 isAnyLowLatencyAppExemptedFromForeground(int[] uids)477 private boolean isAnyLowLatencyAppExemptedFromForeground(int[] uids) { 478 if (uids == null) return false; 479 for (int uid : uids) { 480 UidRec uidRec = mLowLatencyUidWatchList.get(uid); 481 if (uidRec != null && uidRec.mIsFgExempted) { 482 return true; 483 } 484 } 485 return false; 486 } 487 isAppExemptedFromImportance(int uid, int importance)488 private boolean isAppExemptedFromImportance(int uid, int importance) { 489 // Exemption for applications running with CAR Mode permissions. 490 if (mWifiPermissionsUtil.checkRequestCompanionProfileAutomotiveProjectionPermission(uid) 491 && (importance 492 <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE)) { 493 return true; 494 } 495 // Add any exemption cases for applications regarding restricting Low latency locks to 496 // running in the foreground. 497 return false; 498 } 499 isAppForeground(final int uid, final int importance)500 private boolean isAppForeground(final int uid, final int importance) { 501 if ((importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND)) { 502 return true; 503 } 504 return isAppExemptedFromImportance(uid, importance); 505 } 506 isAnyLowLatencyAppExemptedFromScreenOn(int[] uids)507 private boolean isAnyLowLatencyAppExemptedFromScreenOn(int[] uids) { 508 if (uids == null) return false; 509 for (int uid : uids) { 510 UidRec uidRec = mLowLatencyUidWatchList.get(uid); 511 if (uidRec != null && uidRec.mIsScreenOnExempted) { 512 return true; 513 } 514 } 515 return false; 516 } 517 isAppExemptedFromScreenOn(int uid)518 private boolean isAppExemptedFromScreenOn(int uid) { 519 // Exemption for applications running with CAR Mode permissions. 520 if (mWifiPermissionsUtil.checkRequestCompanionProfileAutomotiveProjectionPermission(uid)) { 521 return true; 522 } 523 // Add more exemptions here 524 return false; 525 } 526 addUidToLlWatchList(int uid)527 private void addUidToLlWatchList(int uid) { 528 UidRec uidRec = mLowLatencyUidWatchList.get(uid); 529 if (uidRec != null) { 530 uidRec.mLockCount++; 531 } else { 532 uidRec = new UidRec(uid); 533 uidRec.mLockCount = 1; 534 mLowLatencyUidWatchList.put(uid, uidRec); 535 notifyLowLatencyOwnershipChanged(); 536 537 uidRec.mIsFg = isAppForeground(uid, 538 mContext.getSystemService(ActivityManager.class).getUidImportance(uid)); 539 // Save the current permission of foreground & 'screen on' exemption. 540 uidRec.mIsFgExempted = isAppExemptedFromImportance(uid, 541 ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND); 542 uidRec.mIsScreenOnExempted = isAppExemptedFromScreenOn(uid); 543 544 if (canActivateLowLatencyLock( 545 uidRec.mIsScreenOnExempted ? IGNORE_SCREEN_STATE_MASK : 0, 546 uidRec)) { 547 // Share the blame for this uid 548 setBlameLowLatencyUid(uid, true); 549 notifyLowLatencyActiveUsersChanged(); 550 } 551 } 552 } 553 removeUidFromLlWatchList(int uid)554 private void removeUidFromLlWatchList(int uid) { 555 UidRec uidRec = mLowLatencyUidWatchList.get(uid); 556 if (uidRec == null) { 557 Log.e(TAG, "Failed to find uid in low-latency watch list"); 558 return; 559 } 560 561 if (uidRec.mLockCount > 0) { 562 uidRec.mLockCount--; 563 } else { 564 Log.e(TAG, "Error, uid record contains no locks"); 565 } 566 if (uidRec.mLockCount == 0) { 567 mLowLatencyUidWatchList.remove(uid); 568 notifyLowLatencyOwnershipChanged(); 569 570 // Remove blame for this UID if it was already set 571 // Note that blame needs to be stopped only if it was started before 572 // to avoid calling the API unnecessarily, since it is reference counted 573 if (canActivateLowLatencyLock(uidRec.mIsScreenOnExempted ? IGNORE_SCREEN_STATE_MASK : 0, 574 uidRec)) { 575 setBlameLowLatencyUid(uid, false); 576 notifyLowLatencyActiveUsersChanged(); 577 } 578 } 579 } 580 addWsToLlWatchList(WorkSource ws)581 private void addWsToLlWatchList(WorkSource ws) { 582 int wsSize = ws.size(); 583 for (int i = 0; i < wsSize; i++) { 584 final int uid = ws.getUid(i); 585 addUidToLlWatchList(uid); 586 } 587 588 final List<WorkChain> workChains = ws.getWorkChains(); 589 if (workChains != null) { 590 for (int i = 0; i < workChains.size(); ++i) { 591 final WorkChain workChain = workChains.get(i); 592 final int uid = workChain.getAttributionUid(); 593 addUidToLlWatchList(uid); 594 } 595 } 596 } 597 removeWsFromLlWatchList(WorkSource ws)598 private void removeWsFromLlWatchList(WorkSource ws) { 599 int wsSize = ws.size(); 600 for (int i = 0; i < wsSize; i++) { 601 final int uid = ws.getUid(i); 602 removeUidFromLlWatchList(uid); 603 } 604 605 final List<WorkChain> workChains = ws.getWorkChains(); 606 if (workChains != null) { 607 for (int i = 0; i < workChains.size(); ++i) { 608 final WorkChain workChain = workChains.get(i); 609 final int uid = workChain.getAttributionUid(); 610 removeUidFromLlWatchList(uid); 611 } 612 } 613 } 614 addLock(WifiLock lock)615 private synchronized boolean addLock(WifiLock lock) { 616 if (mVerboseLoggingEnabled) { 617 Log.d(TAG, "addLock: " + lock); 618 } 619 620 if (findLockByBinder(lock.getBinder()) != null) { 621 if (mVerboseLoggingEnabled) { 622 Log.d(TAG, "attempted to add a lock when already holding one"); 623 } 624 return false; 625 } 626 627 mWifiLocks.add(lock); 628 629 switch(lock.mMode) { 630 case WifiManager.WIFI_MODE_FULL_HIGH_PERF: 631 ++mFullHighPerfLocksAcquired; 632 // Start blaming this worksource if conditions are met 633 if (canActivateHighPerfLock()) { 634 setBlameHiPerfWs(lock.mWorkSource, true); 635 } 636 break; 637 case WifiManager.WIFI_MODE_FULL_LOW_LATENCY: 638 addWsToLlWatchList(lock.getWorkSource()); 639 ++mFullLowLatencyLocksAcquired; 640 break; 641 default: 642 // Do nothing 643 break; 644 } 645 646 // Recalculate the operating mode 647 updateOpMode(); 648 649 return true; 650 } 651 removeLock(IBinder binder)652 private synchronized WifiLock removeLock(IBinder binder) { 653 WifiLock lock = findLockByBinder(binder); 654 if (lock != null) { 655 mWifiLocks.remove(lock); 656 lock.unlinkDeathRecipient(); 657 } 658 return lock; 659 } 660 releaseLock(IBinder binder)661 private synchronized boolean releaseLock(IBinder binder) { 662 WifiLock wifiLock = removeLock(binder); 663 if (wifiLock == null) { 664 // attempting to release a lock that does not exist. 665 return false; 666 } 667 668 if (mVerboseLoggingEnabled) { 669 Log.d(TAG, "releaseLock: " + wifiLock); 670 } 671 672 WorkSource ws = wifiLock.getWorkSource(); 673 Pair<int[], String[]> uidsAndTags = WorkSourceUtil.getUidsAndTagsForWs(ws); 674 675 switch(wifiLock.mMode) { 676 case WifiManager.WIFI_MODE_FULL_HIGH_PERF: 677 mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 678 uidsAndTags.first, 679 uidsAndTags.second, 680 mWifiPermissionsUtil.getWifiCallerType(wifiLock.getUid(), 681 ws.getPackageName(0)), 682 mClock.getElapsedSinceBootMillis() - wifiLock.getAcqTimestamp(), 683 canDisableChipPowerSave(), 684 false, 685 false); 686 ++mFullHighPerfLocksReleased; 687 // Stop blaming only if blaming was set before (conditions are met). 688 // This is to avoid calling the api unncessarily, since this API is 689 // reference counted in batteryStats and statsd 690 if (canActivateHighPerfLock()) { 691 setBlameHiPerfWs(wifiLock.mWorkSource, false); 692 } 693 break; 694 case WifiManager.WIFI_MODE_FULL_LOW_LATENCY: 695 mWifiMetrics.addWifiLockAcqSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 696 uidsAndTags.first, 697 uidsAndTags.second, 698 mWifiPermissionsUtil.getWifiCallerType(wifiLock.getUid(), 699 ws.getPackageName(0)), 700 mClock.getElapsedSinceBootMillis() - wifiLock.getAcqTimestamp(), 701 canDisableChipPowerSave(), 702 isAnyLowLatencyAppExemptedFromScreenOn(uidsAndTags.first), 703 isAnyLowLatencyAppExemptedFromForeground(uidsAndTags.first)); 704 removeWsFromLlWatchList(wifiLock.getWorkSource()); 705 ++mFullLowLatencyLocksReleased; 706 break; 707 default: 708 // Do nothing 709 break; 710 } 711 712 // Recalculate the operating mode 713 updateOpMode(); 714 715 return true; 716 } 717 718 /** 719 * Reset the given ClientModeManager's power save/low latency mode to the default. 720 * The method calls needed to reset is the reverse of the method calls used to set. 721 * @return true if the operation succeeded, false otherwise 722 */ resetCurrentMode(@onNull ClientModeManager clientModeManager)723 private boolean resetCurrentMode(@NonNull ClientModeManager clientModeManager) { 724 Pair<int[], String[]> uidsAndTags = null; 725 switch (mCurrentOpMode) { 726 case WifiManager.WIFI_MODE_FULL_HIGH_PERF: 727 if (!setPowerSave(clientModeManager, ClientMode.POWER_SAVE_CLIENT_WIFI_LOCK, 728 true)) { 729 Log.e(TAG, "Failed to reset the OpMode from hi-perf to Normal"); 730 return false; 731 } 732 uidsAndTags = WorkSourceUtil.getUidsAndTagsForWs(mHighPerfBlamedWorkSource); 733 mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_HIGH_PERF, 734 uidsAndTags.first, 735 uidsAndTags.second, 736 mClock.getElapsedSinceBootMillis() - mCurrentSessionStartTimeMs, 737 canDisableChipPowerSave(), 738 false, 739 false); 740 mHighPerfBlamedWorkSource.clear(); 741 break; 742 743 case WifiManager.WIFI_MODE_FULL_LOW_LATENCY: 744 if (!setLowLatencyMode(clientModeManager, false)) { 745 Log.e(TAG, "Failed to reset the OpMode from low-latency to Normal"); 746 return false; 747 } 748 uidsAndTags = WorkSourceUtil.getUidsAndTagsForWs(mLowLatencyBlamedWorkSource); 749 mWifiMetrics.addWifiLockActiveSession(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, 750 uidsAndTags.first, 751 uidsAndTags.second, 752 mClock.getElapsedSinceBootMillis() - mCurrentSessionStartTimeMs, 753 canDisableChipPowerSave(), 754 isAnyLowLatencyAppExemptedFromScreenOn(uidsAndTags.first), 755 isAnyLowLatencyAppExemptedFromForeground(uidsAndTags.first)); 756 mLowLatencyBlamedWorkSource.clear(); 757 break; 758 759 case WifiManager.WIFI_MODE_NO_LOCKS_HELD: 760 default: 761 // No action 762 break; 763 } 764 765 // reset the current mode 766 mCurrentOpMode = WifiManager.WIFI_MODE_NO_LOCKS_HELD; 767 return true; 768 } 769 770 /** 771 * Set power save mode with an overlay check. It's a wrapper for 772 * {@link ClientModeImpl#setPowerSave(int, boolean)}. 773 */ setPowerSave(@onNull ClientModeManager clientModeManager, @ClientMode.PowerSaveClientType int client, boolean ps)774 private boolean setPowerSave(@NonNull ClientModeManager clientModeManager, 775 @ClientMode.PowerSaveClientType int client, boolean ps) { 776 // Check the overlay allows lock to control chip power save. 777 if (canDisableChipPowerSave()) { 778 return clientModeManager.setPowerSave(client, ps); 779 } 780 // Otherwise, pretend the call is a success. 781 return true; 782 } 783 784 /** 785 * Set the new lock mode on the given ClientModeManager 786 * @return true if the operation succeeded, false otherwise 787 */ setNewMode(@onNull ClientModeManager clientModeManager, int newLockMode)788 private boolean setNewMode(@NonNull ClientModeManager clientModeManager, int newLockMode) { 789 switch (newLockMode) { 790 case WifiManager.WIFI_MODE_FULL_HIGH_PERF: 791 if (!setPowerSave(clientModeManager, ClientMode.POWER_SAVE_CLIENT_WIFI_LOCK, 792 false)) { 793 Log.e(TAG, "Failed to set the OpMode to hi-perf"); 794 return false; 795 } 796 mCurrentSessionStartTimeMs = mClock.getElapsedSinceBootMillis(); 797 break; 798 799 case WifiManager.WIFI_MODE_FULL_LOW_LATENCY: 800 if (!setLowLatencyMode(clientModeManager, true)) { 801 Log.e(TAG, "Failed to set the OpMode to low-latency"); 802 return false; 803 } 804 mCurrentSessionStartTimeMs = mClock.getElapsedSinceBootMillis(); 805 break; 806 807 case WifiManager.WIFI_MODE_NO_LOCKS_HELD: 808 // No action 809 break; 810 811 default: 812 // Invalid mode, don't change currentOpMode, and exit with error 813 Log.e(TAG, "Invalid new opMode: " + newLockMode); 814 return false; 815 } 816 817 // Now set the mode to the new value 818 mCurrentOpMode = newLockMode; 819 return true; 820 } 821 updateOpMode()822 private synchronized boolean updateOpMode() { 823 final int newLockMode = getStrongestLockMode(); 824 825 if (newLockMode == mCurrentOpMode) { 826 // No action is needed 827 return true; 828 } 829 830 if (mVerboseLoggingEnabled) { 831 Log.d(TAG, "Current opMode: " + mCurrentOpMode 832 + " New LockMode: " + newLockMode); 833 } 834 835 ClientModeManager primaryManager = mActiveModeWarden.getPrimaryClientModeManager(); 836 837 // Otherwise, we need to change current mode, first reset it to normal 838 if (!resetCurrentMode(primaryManager)) { 839 return false; 840 } 841 842 // Now switch to the new opMode 843 return setNewMode(primaryManager, newLockMode); 844 } 845 846 /** Returns the cached low latency mode support value, or tries to fetch it if not yet known. */ getLowLatencyModeSupport()847 private int getLowLatencyModeSupport() { 848 if (mLatencyModeSupport != LOW_LATENCY_SUPPORT_UNDEFINED) { 849 return mLatencyModeSupport; 850 } 851 852 long supportedFeatures = 853 mActiveModeWarden.getPrimaryClientModeManager().getSupportedFeatures(); 854 if (supportedFeatures == 0L) { 855 return LOW_LATENCY_SUPPORT_UNDEFINED; 856 } 857 858 if ((supportedFeatures & WifiManager.WIFI_FEATURE_LOW_LATENCY) != 0) { 859 mLatencyModeSupport = LOW_LATENCY_SUPPORTED; 860 } else { 861 mLatencyModeSupport = LOW_LATENCY_NOT_SUPPORTED; 862 } 863 return mLatencyModeSupport; 864 } 865 setLowLatencyMode(ClientModeManager clientModeManager, boolean enabled)866 private boolean setLowLatencyMode(ClientModeManager clientModeManager, boolean enabled) { 867 int lowLatencySupport = getLowLatencyModeSupport(); 868 869 if (lowLatencySupport == LOW_LATENCY_SUPPORT_UNDEFINED) { 870 // Support undefined, no action is taken 871 return false; 872 } 873 874 if (lowLatencySupport == LOW_LATENCY_SUPPORTED) { 875 if (!clientModeManager.setLowLatencyMode(enabled)) { 876 Log.e(TAG, "Failed to set low latency mode"); 877 return false; 878 } 879 880 if (!setPowerSave(clientModeManager, ClientMode.POWER_SAVE_CLIENT_WIFI_LOCK, 881 !enabled)) { 882 Log.e(TAG, "Failed to set power save mode"); 883 // Revert the low latency mode 884 clientModeManager.setLowLatencyMode(!enabled); 885 return false; 886 } 887 } else if (lowLatencySupport == LOW_LATENCY_NOT_SUPPORTED) { 888 // Only set power save mode 889 if (!setPowerSave(clientModeManager, ClientMode.POWER_SAVE_CLIENT_WIFI_LOCK, 890 !enabled)) { 891 Log.e(TAG, "Failed to set power save mode"); 892 return false; 893 } 894 } 895 896 mIsLowLatencyActivated = enabled; 897 notifyLowLatencyActivated(); 898 notifyLowLatencyActiveUsersChanged(); 899 return true; 900 } 901 getLowLatencyLockOwners()902 private int[] getLowLatencyLockOwners() { 903 int[] owners = new int[mLowLatencyUidWatchList.size()]; 904 for (int idx = 0; idx < mLowLatencyUidWatchList.size(); idx++) { 905 owners[idx] = mLowLatencyUidWatchList.valueAt(idx).mUid; 906 } 907 return owners; 908 } 909 getLowLatencyActiveUsers()910 private int[] getLowLatencyActiveUsers() { 911 // Return empty array if low latency mode is not activated. Otherwise, return UIDs which are 912 // in foreground or exempted. 913 if (!mIsLowLatencyActivated) return new int[0]; 914 ArrayList<Integer> activeUsers = new ArrayList<>(); 915 for (int idx = 0; idx < mLowLatencyUidWatchList.size(); idx++) { 916 if (mLowLatencyUidWatchList.valueAt(idx).mIsFg) { 917 activeUsers.add(mLowLatencyUidWatchList.valueAt(idx).mUid); 918 } 919 } 920 return activeUsers.stream().mapToInt(i->i).toArray(); 921 } 922 923 /** 924 * See {@link WifiManager#addWifiLowLatencyLockListener(Executor, 925 * WifiManager.WifiLowLatencyLockListener)} 926 */ addWifiLowLatencyLockListener(@onNull IWifiLowLatencyLockListener listener)927 public boolean addWifiLowLatencyLockListener(@NonNull IWifiLowLatencyLockListener listener) { 928 if (!mWifiLowLatencyLockListeners.register(listener)) { 929 return false; 930 } 931 // Notify the new listener about the current enablement of low latency mode. 932 try { 933 listener.onActivatedStateChanged(mIsLowLatencyActivated); 934 listener.onOwnershipChanged(getLowLatencyLockOwners()); 935 if (mIsLowLatencyActivated) { 936 listener.onActiveUsersChanged(getLowLatencyActiveUsers()); 937 } 938 } catch (RemoteException e) { 939 Log.e(TAG, "addWifiLowLatencyLockListener: Failure notifying listener" + e); 940 } 941 return true; 942 } 943 944 /** 945 * See 946 * {@link WifiManager#removeWifiLowLatencyLockListener(WifiManager.WifiLowLatencyLockListener)} 947 */ removeWifiLowLatencyLockListener(@onNull IWifiLowLatencyLockListener listener)948 public boolean removeWifiLowLatencyLockListener(@NonNull IWifiLowLatencyLockListener listener) { 949 return mWifiLowLatencyLockListeners.unregister(listener); 950 } 951 notifyLowLatencyActivated()952 private void notifyLowLatencyActivated() { 953 int numCallbacks = mWifiLowLatencyLockListeners.beginBroadcast(); 954 if (mVerboseLoggingEnabled) { 955 Log.i(TAG, "Broadcasting IWifiLowLatencyLockListener#onActivatedStateChanged activated=" 956 + mIsLowLatencyActivated); 957 } 958 for (int i = 0; i < numCallbacks; i++) { 959 try { 960 mWifiLowLatencyLockListeners.getBroadcastItem(i).onActivatedStateChanged( 961 mIsLowLatencyActivated); 962 } catch (RemoteException e) { 963 Log.e(TAG, 964 "Failure broadcasting IWifiLowLatencyLockListener#onActivatedStateChanged" 965 + e); 966 } 967 } 968 mWifiLowLatencyLockListeners.finishBroadcast(); 969 } 970 notifyLowLatencyOwnershipChanged()971 private void notifyLowLatencyOwnershipChanged() { 972 int numCallbacks = mWifiLowLatencyLockListeners.beginBroadcast(); 973 int[] owners = getLowLatencyLockOwners(); 974 if (mVerboseLoggingEnabled) { 975 Log.i(TAG, "Broadcasting IWifiLowLatencyLockListener#onOwnershipChanged: UIDs " 976 + Arrays.toString(owners)); 977 } 978 for (int i = 0; i < numCallbacks; i++) { 979 try { 980 mWifiLowLatencyLockListeners.getBroadcastItem(i).onOwnershipChanged(owners); 981 } catch (RemoteException e) { 982 Log.e(TAG, 983 "Failure broadcasting IWifiLowLatencyLockListener#onOwnershipChanged" + e); 984 } 985 } 986 mWifiLowLatencyLockListeners.finishBroadcast(); 987 } 988 notifyLowLatencyActiveUsersChanged()989 private void notifyLowLatencyActiveUsersChanged() { 990 if (!mIsLowLatencyActivated) return; 991 int numCallbacks = mWifiLowLatencyLockListeners.beginBroadcast(); 992 int[] activeUsers = getLowLatencyActiveUsers(); 993 if (mVerboseLoggingEnabled) { 994 Log.i(TAG, "Broadcasting IWifiLowLatencyLockListener#onActiveUsersChanged: UIDs " 995 + Arrays.toString(activeUsers)); 996 } 997 for (int i = 0; i < numCallbacks; i++) { 998 try { 999 mWifiLowLatencyLockListeners.getBroadcastItem(i).onActiveUsersChanged(activeUsers); 1000 } catch (RemoteException e) { 1001 Log.e(TAG, "Failure broadcasting IWifiLowLatencyLockListener#onActiveUsersChanged" 1002 + e); 1003 } 1004 } 1005 mWifiLowLatencyLockListeners.finishBroadcast(); 1006 } 1007 findLockByBinder(IBinder binder)1008 private synchronized WifiLock findLockByBinder(IBinder binder) { 1009 for (WifiLock lock : mWifiLocks) { 1010 if (lock.getBinder() == binder) { 1011 return lock; 1012 } 1013 } 1014 return null; 1015 } 1016 countFgLowLatencyUids(boolean isScreenOnExempted)1017 private int countFgLowLatencyUids(boolean isScreenOnExempted) { 1018 int uidCount = 0; 1019 int listSize = mLowLatencyUidWatchList.size(); 1020 for (int idx = 0; idx < listSize; idx++) { 1021 UidRec uidRec = mLowLatencyUidWatchList.valueAt(idx); 1022 if (uidRec.mIsFg) { 1023 if (isScreenOnExempted) { 1024 if (uidRec.mIsScreenOnExempted) uidCount++; 1025 } else { 1026 uidCount++; 1027 } 1028 } 1029 } 1030 return uidCount; 1031 } 1032 setBlameHiPerfWs(WorkSource ws, boolean shouldBlame)1033 private void setBlameHiPerfWs(WorkSource ws, boolean shouldBlame) { 1034 long ident = Binder.clearCallingIdentity(); 1035 Pair<int[], String[]> uidsAndTags = WorkSourceUtil.getUidsAndTagsForWs(ws); 1036 try { 1037 if (shouldBlame) { 1038 mHighPerfBlamedWorkSource.add(ws); 1039 mBatteryStats.reportFullWifiLockAcquiredFromSource(ws); 1040 WifiStatsLog.write(WifiStatsLog.WIFI_LOCK_STATE_CHANGED, 1041 uidsAndTags.first, uidsAndTags.second, 1042 WifiStatsLog.WIFI_LOCK_STATE_CHANGED__STATE__ON, 1043 WifiStatsLog.WIFI_LOCK_STATE_CHANGED__MODE__WIFI_MODE_FULL_HIGH_PERF); 1044 } else { 1045 mBatteryStats.reportFullWifiLockReleasedFromSource(ws); 1046 WifiStatsLog.write(WifiStatsLog.WIFI_LOCK_STATE_CHANGED, 1047 uidsAndTags.first, uidsAndTags.second, 1048 WifiStatsLog.WIFI_LOCK_STATE_CHANGED__STATE__OFF, 1049 WifiStatsLog.WIFI_LOCK_STATE_CHANGED__MODE__WIFI_MODE_FULL_HIGH_PERF); 1050 } 1051 } finally { 1052 Binder.restoreCallingIdentity(ident); 1053 } 1054 } 1055 setBlameLowLatencyUid(int uid, boolean shouldBlame)1056 private void setBlameLowLatencyUid(int uid, boolean shouldBlame) { 1057 long ident = Binder.clearCallingIdentity(); 1058 try { 1059 if (shouldBlame) { 1060 mLowLatencyBlamedWorkSource.add(new WorkSource(uid)); 1061 mBatteryStats.reportFullWifiLockAcquiredFromSource(new WorkSource(uid)); 1062 WifiStatsLog.write_non_chained(WifiStatsLog.WIFI_LOCK_STATE_CHANGED, uid, null, 1063 WifiStatsLog.WIFI_LOCK_STATE_CHANGED__STATE__ON, 1064 WifiStatsLog.WIFI_LOCK_STATE_CHANGED__MODE__WIFI_MODE_FULL_LOW_LATENCY); 1065 } else { 1066 mBatteryStats.reportFullWifiLockReleasedFromSource(new WorkSource(uid)); 1067 WifiStatsLog.write_non_chained(WifiStatsLog.WIFI_LOCK_STATE_CHANGED, uid, null, 1068 WifiStatsLog.WIFI_LOCK_STATE_CHANGED__STATE__OFF, 1069 WifiStatsLog.WIFI_LOCK_STATE_CHANGED__MODE__WIFI_MODE_FULL_LOW_LATENCY); 1070 } 1071 } finally { 1072 Binder.restoreCallingIdentity(ident); 1073 } 1074 } 1075 setBlameLowLatencyWatchList(BlameReason reason, boolean shouldBlame)1076 private void setBlameLowLatencyWatchList(BlameReason reason, boolean shouldBlame) { 1077 boolean notify = false; 1078 for (int idx = 0; idx < mLowLatencyUidWatchList.size(); idx++) { 1079 UidRec uidRec = mLowLatencyUidWatchList.valueAt(idx); 1080 // The blame state of the UIDs should not be changed if the app is exempted from 1081 // screen-on and the reason for blaming is screen state change. 1082 if (uidRec.mIsScreenOnExempted && reason == BlameReason.SCREEN_STATE_CHANGED) { 1083 continue; 1084 } 1085 // Affect the blame for only UIDs running in foreground 1086 // UIDs running in the background are already not blamed, 1087 // and they should remain in that state. 1088 if (uidRec.mIsFg) { 1089 setBlameLowLatencyUid(uidRec.mUid, shouldBlame); 1090 notify = true; 1091 } 1092 } 1093 if (notify) notifyLowLatencyActiveUsersChanged(); 1094 } 1095 dump(PrintWriter pw)1096 protected synchronized void dump(PrintWriter pw) { 1097 pw.println("Locks acquired: " 1098 + mFullHighPerfLocksAcquired + " full high perf, " 1099 + mFullLowLatencyLocksAcquired + " full low latency"); 1100 pw.println("Locks released: " 1101 + mFullHighPerfLocksReleased + " full high perf, " 1102 + mFullLowLatencyLocksReleased + " full low latency"); 1103 1104 pw.println(); 1105 pw.println("Locks held:"); 1106 for (WifiLock lock : mWifiLocks) { 1107 pw.print(" "); 1108 pw.println(lock); 1109 } 1110 } 1111 enableVerboseLogging(boolean verboseEnabled)1112 protected void enableVerboseLogging(boolean verboseEnabled) { 1113 mVerboseLoggingEnabled = verboseEnabled; 1114 } 1115 1116 private class WifiLock implements IBinder.DeathRecipient { 1117 String mTag; 1118 int mUid; 1119 IBinder mBinder; 1120 int mMode; 1121 WorkSource mWorkSource; 1122 long mAcqTimestamp; 1123 WifiLock(int lockMode, String tag, IBinder binder, WorkSource ws)1124 WifiLock(int lockMode, String tag, IBinder binder, WorkSource ws) { 1125 mTag = tag; 1126 mBinder = binder; 1127 mUid = Binder.getCallingUid(); 1128 mMode = lockMode; 1129 mWorkSource = ws; 1130 mAcqTimestamp = mClock.getElapsedSinceBootMillis(); 1131 try { 1132 mBinder.linkToDeath(this, 0); 1133 } catch (RemoteException e) { 1134 Log.e(TAG, "mBinder.linkToDeath failed: " + e.getMessage()); 1135 binderDied(); 1136 } 1137 } 1138 getWorkSource()1139 protected WorkSource getWorkSource() { 1140 return mWorkSource; 1141 } 1142 getUid()1143 protected int getUid() { 1144 return mUid; 1145 } 1146 getBinder()1147 protected IBinder getBinder() { 1148 return mBinder; 1149 } 1150 getAcqTimestamp()1151 protected long getAcqTimestamp() { 1152 return mAcqTimestamp; 1153 } 1154 binderDied()1155 public void binderDied() { 1156 mHandler.post(() -> releaseLock(mBinder)); 1157 } 1158 unlinkDeathRecipient()1159 public void unlinkDeathRecipient() { 1160 try { 1161 mBinder.unlinkToDeath(this, 0); 1162 } catch (NoSuchElementException e) { 1163 Log.e(TAG, "mBinder.unlinkToDeath failed: " + e.getMessage()); 1164 } 1165 } 1166 toString()1167 public String toString() { 1168 return "WifiLock{" + this.mTag + " type=" + this.mMode + " uid=" + mUid 1169 + " workSource=" + mWorkSource + "}"; 1170 } 1171 } 1172 1173 private class UidRec { 1174 final int mUid; 1175 // Count of locks owned or co-owned by this UID 1176 int mLockCount; 1177 // Is this UID running in foreground or in exempted state (e.g. foreground-service) 1178 boolean mIsFg; 1179 boolean mIsFgExempted = false; 1180 boolean mIsScreenOnExempted = false; 1181 UidRec(int uid)1182 UidRec(int uid) { 1183 mUid = uid; 1184 } 1185 } 1186 } 1187