1 /* 2 * Copyright (C) 2019 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 android.os; 18 19 import android.annotation.IntDef; 20 import android.annotation.IntRange; 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.annotation.RequiresPermission; 24 import android.annotation.SystemApi; 25 import android.annotation.SystemService; 26 import android.annotation.TestApi; 27 import android.content.Context; 28 import android.net.NetworkStack; 29 import android.os.connectivity.CellularBatteryStats; 30 import android.os.connectivity.WifiBatteryStats; 31 import android.telephony.DataConnectionRealTimeInfo; 32 33 import com.android.internal.app.IBatteryStats; 34 35 import java.lang.annotation.Retention; 36 import java.lang.annotation.RetentionPolicy; 37 import java.util.List; 38 39 /** 40 * This class provides an API surface for internal system components to report events that are 41 * needed for battery usage/estimation and battery blaming for apps. 42 * 43 * Note: This internally uses the same {@link IBatteryStats} binder service as the public 44 * {@link BatteryManager}. 45 * @hide 46 */ 47 @SystemApi 48 @SystemService(Context.BATTERY_STATS_SERVICE) 49 public final class BatteryStatsManager { 50 /** 51 * Wifi states. 52 * 53 * @see #noteWifiState(int, String) 54 */ 55 /** 56 * Wifi fully off. 57 */ 58 public static final int WIFI_STATE_OFF = 0; 59 /** 60 * Wifi connectivity off, but scanning enabled. 61 */ 62 public static final int WIFI_STATE_OFF_SCANNING = 1; 63 /** 64 * Wifi on, but no saved infrastructure networks to connect to. 65 */ 66 public static final int WIFI_STATE_ON_NO_NETWORKS = 2; 67 /** 68 * Wifi on, but not connected to any infrastructure networks. 69 */ 70 public static final int WIFI_STATE_ON_DISCONNECTED = 3; 71 /** 72 * Wifi on and connected to a infrastructure network. 73 */ 74 public static final int WIFI_STATE_ON_CONNECTED_STA = 4; 75 /** 76 * Wifi on and connected to a P2P device, but no infrastructure connection to a network. 77 */ 78 public static final int WIFI_STATE_ON_CONNECTED_P2P = 5; 79 /** 80 * Wifi on and connected to both a P2P device and infrastructure connection to a network. 81 */ 82 public static final int WIFI_STATE_ON_CONNECTED_STA_P2P = 6; 83 /** 84 * SoftAp/Hotspot turned on. 85 */ 86 public static final int WIFI_STATE_SOFT_AP = 7; 87 88 /** @hide */ 89 public static final int NUM_WIFI_STATES = WIFI_STATE_SOFT_AP + 1; 90 91 /** @hide */ 92 @IntDef(prefix = { "WIFI_STATE_" }, value = { 93 WIFI_STATE_OFF, 94 WIFI_STATE_OFF_SCANNING, 95 WIFI_STATE_ON_NO_NETWORKS, 96 WIFI_STATE_ON_DISCONNECTED, 97 WIFI_STATE_ON_CONNECTED_STA, 98 WIFI_STATE_ON_CONNECTED_P2P, 99 WIFI_STATE_ON_CONNECTED_STA_P2P, 100 WIFI_STATE_SOFT_AP 101 }) 102 @Retention(RetentionPolicy.SOURCE) 103 public @interface WifiState {} 104 105 /** 106 * Wifi supplicant daemon states. 107 * 108 * @see android.net.wifi.SupplicantState for detailed description of states. 109 * @see #noteWifiSupplicantStateChanged(int) 110 */ 111 /** @see android.net.wifi.SupplicantState#INVALID */ 112 public static final int WIFI_SUPPL_STATE_INVALID = 0; 113 /** @see android.net.wifi.SupplicantState#DISCONNECTED*/ 114 public static final int WIFI_SUPPL_STATE_DISCONNECTED = 1; 115 /** @see android.net.wifi.SupplicantState#INTERFACE_DISABLED */ 116 public static final int WIFI_SUPPL_STATE_INTERFACE_DISABLED = 2; 117 /** @see android.net.wifi.SupplicantState#INACTIVE*/ 118 public static final int WIFI_SUPPL_STATE_INACTIVE = 3; 119 /** @see android.net.wifi.SupplicantState#SCANNING*/ 120 public static final int WIFI_SUPPL_STATE_SCANNING = 4; 121 /** @see android.net.wifi.SupplicantState#AUTHENTICATING */ 122 public static final int WIFI_SUPPL_STATE_AUTHENTICATING = 5; 123 /** @see android.net.wifi.SupplicantState#ASSOCIATING */ 124 public static final int WIFI_SUPPL_STATE_ASSOCIATING = 6; 125 /** @see android.net.wifi.SupplicantState#ASSOCIATED */ 126 public static final int WIFI_SUPPL_STATE_ASSOCIATED = 7; 127 /** @see android.net.wifi.SupplicantState#FOUR_WAY_HANDSHAKE */ 128 public static final int WIFI_SUPPL_STATE_FOUR_WAY_HANDSHAKE = 8; 129 /** @see android.net.wifi.SupplicantState#GROUP_HANDSHAKE */ 130 public static final int WIFI_SUPPL_STATE_GROUP_HANDSHAKE = 9; 131 /** @see android.net.wifi.SupplicantState#COMPLETED */ 132 public static final int WIFI_SUPPL_STATE_COMPLETED = 10; 133 /** @see android.net.wifi.SupplicantState#DORMANT */ 134 public static final int WIFI_SUPPL_STATE_DORMANT = 11; 135 /** @see android.net.wifi.SupplicantState#UNINITIALIZED */ 136 public static final int WIFI_SUPPL_STATE_UNINITIALIZED = 12; 137 138 /** @hide */ 139 public static final int NUM_WIFI_SUPPL_STATES = WIFI_SUPPL_STATE_UNINITIALIZED + 1; 140 141 /** @hide */ 142 @IntDef(prefix = { "WIFI_SUPPL_STATE_" }, value = { 143 WIFI_SUPPL_STATE_INVALID, 144 WIFI_SUPPL_STATE_DISCONNECTED, 145 WIFI_SUPPL_STATE_INTERFACE_DISABLED, 146 WIFI_SUPPL_STATE_INACTIVE, 147 WIFI_SUPPL_STATE_SCANNING, 148 WIFI_SUPPL_STATE_AUTHENTICATING, 149 WIFI_SUPPL_STATE_ASSOCIATING, 150 WIFI_SUPPL_STATE_ASSOCIATED, 151 WIFI_SUPPL_STATE_FOUR_WAY_HANDSHAKE, 152 WIFI_SUPPL_STATE_GROUP_HANDSHAKE, 153 WIFI_SUPPL_STATE_COMPLETED, 154 WIFI_SUPPL_STATE_DORMANT, 155 WIFI_SUPPL_STATE_UNINITIALIZED, 156 }) 157 @Retention(RetentionPolicy.SOURCE) 158 public @interface WifiSupplState {} 159 160 private final IBatteryStats mBatteryStats; 161 162 /** @hide */ BatteryStatsManager(IBatteryStats batteryStats)163 public BatteryStatsManager(IBatteryStats batteryStats) { 164 mBatteryStats = batteryStats; 165 } 166 167 168 /** 169 * Returns BatteryUsageStats, which contains power attribution data on a per-subsystem 170 * and per-UID basis. 171 * 172 * @hide 173 */ 174 @RequiresPermission(android.Manifest.permission.BATTERY_STATS) 175 @NonNull getBatteryUsageStats()176 public BatteryUsageStats getBatteryUsageStats() { 177 return getBatteryUsageStats(BatteryUsageStatsQuery.DEFAULT); 178 } 179 180 /** 181 * Returns BatteryUsageStats, which contains power attribution data on a per-subsystem 182 * and per-UID basis. 183 * 184 * @hide 185 */ 186 @RequiresPermission(android.Manifest.permission.BATTERY_STATS) 187 @NonNull getBatteryUsageStats(BatteryUsageStatsQuery query)188 public BatteryUsageStats getBatteryUsageStats(BatteryUsageStatsQuery query) { 189 return getBatteryUsageStats(List.of(query)).get(0); 190 } 191 192 /** 193 * Returns BatteryUsageStats, which contains power attribution data on a per-subsystem 194 * and per-UID basis. 195 * 196 * @hide 197 */ 198 @RequiresPermission(android.Manifest.permission.BATTERY_STATS) 199 @NonNull getBatteryUsageStats(List<BatteryUsageStatsQuery> queries)200 public List<BatteryUsageStats> getBatteryUsageStats(List<BatteryUsageStatsQuery> queries) { 201 try { 202 return mBatteryStats.getBatteryUsageStats(queries); 203 } catch (RemoteException e) { 204 throw e.rethrowFromSystemServer(); 205 } 206 } 207 208 /** 209 * Indicates that the wifi connection RSSI has changed. 210 * 211 * @param newRssi The new RSSI value. 212 */ 213 @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) reportWifiRssiChanged(@ntRangefrom = -127, to = 0) int newRssi)214 public void reportWifiRssiChanged(@IntRange(from = -127, to = 0) int newRssi) { 215 try { 216 mBatteryStats.noteWifiRssiChanged(newRssi); 217 } catch (RemoteException e) { 218 e.rethrowFromSystemServer(); 219 } 220 } 221 222 /** 223 * Indicates that wifi was toggled on. 224 */ 225 @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) reportWifiOn()226 public void reportWifiOn() { 227 try { 228 mBatteryStats.noteWifiOn(); 229 } catch (RemoteException e) { 230 e.rethrowFromSystemServer(); 231 } 232 } 233 234 /** 235 * Indicates that wifi was toggled off. 236 */ 237 @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) reportWifiOff()238 public void reportWifiOff() { 239 try { 240 mBatteryStats.noteWifiOff(); 241 } catch (RemoteException e) { 242 e.rethrowFromSystemServer(); 243 } 244 } 245 246 /** 247 * Indicates that wifi state has changed. 248 * 249 * @param newWifiState The new wifi State. 250 * @param accessPoint SSID of the network if wifi is connected to STA, else null. 251 */ 252 @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) reportWifiState(@ifiState int newWifiState, @Nullable String accessPoint)253 public void reportWifiState(@WifiState int newWifiState, 254 @Nullable String accessPoint) { 255 try { 256 mBatteryStats.noteWifiState(newWifiState, accessPoint); 257 } catch (RemoteException e) { 258 e.rethrowFromSystemServer(); 259 } 260 } 261 262 /** 263 * Indicates that a new wifi scan has started. 264 * 265 * @param ws Worksource (to be used for battery blaming). 266 */ 267 @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) reportWifiScanStartedFromSource(@onNull WorkSource ws)268 public void reportWifiScanStartedFromSource(@NonNull WorkSource ws) { 269 try { 270 mBatteryStats.noteWifiScanStartedFromSource(ws); 271 } catch (RemoteException e) { 272 e.rethrowFromSystemServer(); 273 } 274 } 275 276 /** 277 * Indicates that an ongoing wifi scan has stopped. 278 * 279 * @param ws Worksource (to be used for battery blaming). 280 */ 281 @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) reportWifiScanStoppedFromSource(@onNull WorkSource ws)282 public void reportWifiScanStoppedFromSource(@NonNull WorkSource ws) { 283 try { 284 mBatteryStats.noteWifiScanStoppedFromSource(ws); 285 } catch (RemoteException e) { 286 e.rethrowFromSystemServer(); 287 } 288 } 289 290 /** 291 * Indicates that a new wifi batched scan has started. 292 * 293 * @param ws Worksource (to be used for battery blaming). 294 * @param csph Channels scanned per hour. 295 */ 296 @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) reportWifiBatchedScanStartedFromSource(@onNull WorkSource ws, @IntRange(from = 0) int csph)297 public void reportWifiBatchedScanStartedFromSource(@NonNull WorkSource ws, 298 @IntRange(from = 0) int csph) { 299 try { 300 mBatteryStats.noteWifiBatchedScanStartedFromSource(ws, csph); 301 } catch (RemoteException e) { 302 e.rethrowFromSystemServer(); 303 } 304 } 305 306 /** 307 * Indicates that an ongoing wifi batched scan has stopped. 308 * 309 * @param ws Worksource (to be used for battery blaming). 310 */ 311 @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) reportWifiBatchedScanStoppedFromSource(@onNull WorkSource ws)312 public void reportWifiBatchedScanStoppedFromSource(@NonNull WorkSource ws) { 313 try { 314 mBatteryStats.noteWifiBatchedScanStoppedFromSource(ws); 315 } catch (RemoteException e) { 316 e.rethrowFromSystemServer(); 317 } 318 } 319 320 /** 321 * Retrieves all the cellular related battery stats. 322 * 323 * @return Instance of {@link CellularBatteryStats}. 324 */ 325 @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) getCellularBatteryStats()326 public @NonNull CellularBatteryStats getCellularBatteryStats() { 327 try { 328 return mBatteryStats.getCellularBatteryStats(); 329 } catch (RemoteException e) { 330 e.rethrowFromSystemServer(); 331 return null; 332 } 333 } 334 335 /** 336 * Retrieves all the wifi related battery stats. 337 * 338 * @return Instance of {@link WifiBatteryStats}. 339 */ 340 @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) getWifiBatteryStats()341 public @NonNull WifiBatteryStats getWifiBatteryStats() { 342 try { 343 return mBatteryStats.getWifiBatteryStats(); 344 } catch (RemoteException e) { 345 e.rethrowFromSystemServer(); 346 return null; 347 } 348 } 349 350 /** 351 * Indicates an app acquiring full wifi lock. 352 * 353 * @param ws Worksource (to be used for battery blaming). 354 */ 355 @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) reportFullWifiLockAcquiredFromSource(@onNull WorkSource ws)356 public void reportFullWifiLockAcquiredFromSource(@NonNull WorkSource ws) { 357 try { 358 mBatteryStats.noteFullWifiLockAcquiredFromSource(ws); 359 } catch (RemoteException e) { 360 e.rethrowFromSystemServer(); 361 } 362 } 363 364 /** 365 * Indicates an app releasing full wifi lock. 366 * 367 * @param ws Worksource (to be used for battery blaming). 368 */ 369 @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) reportFullWifiLockReleasedFromSource(@onNull WorkSource ws)370 public void reportFullWifiLockReleasedFromSource(@NonNull WorkSource ws) { 371 try { 372 mBatteryStats.noteFullWifiLockReleasedFromSource(ws); 373 } catch (RemoteException e) { 374 e.rethrowFromSystemServer(); 375 } 376 } 377 378 /** 379 * Indicates that supplicant state has changed. 380 * 381 * @param newSupplState The new Supplicant state. 382 * @param failedAuth Boolean indicating whether there was a connection failure due to 383 * authentication failure. 384 */ 385 @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) reportWifiSupplicantStateChanged(@ifiSupplState int newSupplState, boolean failedAuth)386 public void reportWifiSupplicantStateChanged(@WifiSupplState int newSupplState, 387 boolean failedAuth) { 388 try { 389 mBatteryStats.noteWifiSupplicantStateChanged(newSupplState, failedAuth); 390 } catch (RemoteException e) { 391 e.rethrowFromSystemServer(); 392 } 393 } 394 395 /** 396 * Indicates that an app has acquired the wifi multicast lock. 397 * 398 * @param ws Worksource with the uid of the app that acquired the wifi lock (to be used for 399 * battery blaming). 400 */ 401 @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) reportWifiMulticastEnabled(@onNull WorkSource ws)402 public void reportWifiMulticastEnabled(@NonNull WorkSource ws) { 403 try { 404 mBatteryStats.noteWifiMulticastEnabled(ws.getAttributionUid()); 405 } catch (RemoteException e) { 406 e.rethrowFromSystemServer(); 407 } 408 } 409 410 /** 411 * Indicates that an app has released the wifi multicast lock. 412 * 413 * @param ws Worksource with the uid of the app that released the wifi lock (to be used for 414 * battery blaming). 415 */ 416 @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) reportWifiMulticastDisabled(@onNull WorkSource ws)417 public void reportWifiMulticastDisabled(@NonNull WorkSource ws) { 418 try { 419 mBatteryStats.noteWifiMulticastDisabled(ws.getAttributionUid()); 420 } catch (RemoteException e) { 421 e.rethrowFromSystemServer(); 422 } 423 } 424 425 /** 426 * Indicates that the radio power state has changed. 427 * 428 * @param isActive indicates if the mobile radio is powered. 429 * @param uid Uid of this event. For the active state it represents the uid that was responsible 430 * for waking the radio, or -1 if the system was responsible for waking the radio. 431 * For inactive state, the UID should always be -1. 432 */ 433 @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) reportMobileRadioPowerState(boolean isActive, int uid)434 public void reportMobileRadioPowerState(boolean isActive, int uid) { 435 try { 436 mBatteryStats.noteMobileRadioPowerState(getDataConnectionPowerState(isActive), 437 SystemClock.elapsedRealtimeNanos(), uid); 438 } catch (RemoteException e) { 439 e.rethrowFromSystemServer(); 440 } 441 } 442 443 /** 444 * Indicates that the wifi power state has changed. 445 * 446 * @param isActive indicates if the wifi radio is powered. 447 * @param uid Uid of this event. For the active state it represents the uid that was responsible 448 * for waking the radio, or -1 if the system was responsible for waking the radio. 449 * For inactive state, the UID should always be -1. 450 */ 451 @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) reportWifiRadioPowerState(boolean isActive, int uid)452 public void reportWifiRadioPowerState(boolean isActive, int uid) { 453 try { 454 mBatteryStats.noteWifiRadioPowerState(getDataConnectionPowerState(isActive), 455 SystemClock.elapsedRealtimeNanos(), uid); 456 } catch (RemoteException e) { 457 e.rethrowFromSystemServer(); 458 } 459 } 460 461 /** 462 * Notifies the battery stats of a new interface, and the transport types of the network that 463 * includes that interface. 464 * 465 * @param iface The interface of the network. 466 * @param transportTypes The transport type of the network {@link Transport}. 467 * @hide 468 */ 469 @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) 470 @RequiresPermission(anyOf = { 471 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, 472 android.Manifest.permission.NETWORK_STACK}) reportNetworkInterfaceForTransports(@onNull String iface, @NonNull int[] transportTypes)473 public void reportNetworkInterfaceForTransports(@NonNull String iface, 474 @NonNull int[] transportTypes) throws RuntimeException { 475 try { 476 mBatteryStats.noteNetworkInterfaceForTransports(iface, transportTypes); 477 } catch (RemoteException e) { 478 e.rethrowFromSystemServer(); 479 } 480 } 481 getDataConnectionPowerState(boolean isActive)482 private static int getDataConnectionPowerState(boolean isActive) { 483 // TODO: DataConnectionRealTimeInfo is under telephony package but the constants are used 484 // for both Wifi and mobile. It would make more sense to separate the constants to a 485 // generic class or move it to generic package. 486 return isActive ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH 487 : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW; 488 } 489 490 /** 491 * Sets battery AC charger to enabled/disabled, and freezes the battery state. 492 * @hide 493 */ 494 @TestApi 495 @RequiresPermission(android.Manifest.permission.DEVICE_POWER) setChargerAcOnline(boolean online, boolean forceUpdate)496 public void setChargerAcOnline(boolean online, boolean forceUpdate) { 497 try { 498 mBatteryStats.setChargerAcOnline(online, forceUpdate); 499 } catch (RemoteException e) { 500 e.rethrowFromSystemServer(); 501 } 502 } 503 504 /** 505 * Sets battery level, and freezes the battery state. 506 * @hide 507 */ 508 @TestApi 509 @RequiresPermission(android.Manifest.permission.DEVICE_POWER) setBatteryLevel(int level, boolean forceUpdate)510 public void setBatteryLevel(int level, boolean forceUpdate) { 511 try { 512 mBatteryStats.setBatteryLevel(level, forceUpdate); 513 } catch (RemoteException e) { 514 e.rethrowFromSystemServer(); 515 } 516 } 517 518 /** 519 * Unplugs battery, and freezes the battery state. 520 * @hide 521 */ 522 @TestApi 523 @RequiresPermission(android.Manifest.permission.DEVICE_POWER) unplugBattery(boolean forceUpdate)524 public void unplugBattery(boolean forceUpdate) { 525 try { 526 mBatteryStats.unplugBattery(forceUpdate); 527 } catch (RemoteException e) { 528 e.rethrowFromSystemServer(); 529 } 530 } 531 532 /** 533 * Unfreezes battery state, returning to current hardware values. 534 * @hide 535 */ 536 @TestApi 537 @RequiresPermission(android.Manifest.permission.DEVICE_POWER) resetBattery(boolean forceUpdate)538 public void resetBattery(boolean forceUpdate) { 539 try { 540 mBatteryStats.resetBattery(forceUpdate); 541 } catch (RemoteException e) { 542 e.rethrowFromSystemServer(); 543 } 544 } 545 546 /** 547 * Suspend charging even if plugged in. 548 * @hide 549 */ 550 @TestApi 551 @RequiresPermission(android.Manifest.permission.DEVICE_POWER) suspendBatteryInput()552 public void suspendBatteryInput() { 553 try { 554 mBatteryStats.suspendBatteryInput(); 555 } catch (RemoteException e) { 556 e.rethrowFromSystemServer(); 557 } 558 } 559 }