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