1 /* 2 * Copyright (C) 2006-2007 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.am; 18 19 import android.bluetooth.BluetoothAdapter; 20 import android.bluetooth.BluetoothHeadset; 21 import android.bluetooth.BluetoothProfile; 22 import android.content.Context; 23 import android.content.pm.ApplicationInfo; 24 import android.content.pm.PackageManager; 25 import android.os.BatteryStats; 26 import android.os.Binder; 27 import android.os.Handler; 28 import android.os.IBinder; 29 import android.os.Parcel; 30 import android.os.ParcelFileDescriptor; 31 import android.os.PowerManagerInternal; 32 import android.os.Process; 33 import android.os.ServiceManager; 34 import android.os.SystemClock; 35 import android.os.UserHandle; 36 import android.os.WorkSource; 37 import android.telephony.SignalStrength; 38 import android.telephony.TelephonyManager; 39 import android.util.Slog; 40 41 import com.android.internal.app.IBatteryStats; 42 import com.android.internal.os.BatteryStatsHelper; 43 import com.android.internal.os.BatteryStatsImpl; 44 import com.android.internal.os.PowerProfile; 45 import com.android.server.LocalServices; 46 47 import java.io.File; 48 import java.io.FileDescriptor; 49 import java.io.FileOutputStream; 50 import java.io.IOException; 51 import java.io.PrintWriter; 52 import java.util.List; 53 54 /** 55 * All information we are collecting about things that can happen that impact 56 * battery life. 57 */ 58 public final class BatteryStatsService extends IBatteryStats.Stub 59 implements PowerManagerInternal.LowPowerModeListener { 60 static final String TAG = "BatteryStatsService"; 61 62 static IBatteryStats sService; 63 64 final BatteryStatsImpl mStats; 65 Context mContext; 66 private boolean mBluetoothPendingStats; 67 private BluetoothHeadset mBluetoothHeadset; 68 PowerManagerInternal mPowerManagerInternal; 69 BatteryStatsService(File systemDir, Handler handler)70 BatteryStatsService(File systemDir, Handler handler) { 71 mStats = new BatteryStatsImpl(systemDir, handler); 72 } 73 publish(Context context)74 public void publish(Context context) { 75 mContext = context; 76 ServiceManager.addService(BatteryStats.SERVICE_NAME, asBinder()); 77 mStats.setNumSpeedSteps(new PowerProfile(mContext).getNumSpeedSteps()); 78 mStats.setRadioScanningTimeout(mContext.getResources().getInteger( 79 com.android.internal.R.integer.config_radioScanningTimeout) 80 * 1000L); 81 } 82 83 /** 84 * At the time when the constructor runs, the power manager has not yet been 85 * initialized. So we initialize the low power observer later. 86 */ initPowerManagement()87 public void initPowerManagement() { 88 mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); 89 mPowerManagerInternal.registerLowPowerModeObserver(this); 90 mStats.noteLowPowerMode(mPowerManagerInternal.getLowPowerModeEnabled()); 91 (new WakeupReasonThread()).start(); 92 } 93 shutdown()94 public void shutdown() { 95 Slog.w("BatteryStats", "Writing battery stats before shutdown..."); 96 synchronized (mStats) { 97 mStats.shutdownLocked(); 98 } 99 } 100 getService()101 public static IBatteryStats getService() { 102 if (sService != null) { 103 return sService; 104 } 105 IBinder b = ServiceManager.getService(BatteryStats.SERVICE_NAME); 106 sService = asInterface(b); 107 return sService; 108 } 109 110 @Override onLowPowerModeChanged(boolean enabled)111 public void onLowPowerModeChanged(boolean enabled) { 112 synchronized (mStats) { 113 mStats.noteLowPowerMode(enabled); 114 } 115 } 116 117 /** 118 * @return the current statistics object, which may be modified 119 * to reflect events that affect battery usage. You must lock the 120 * stats object before doing anything with it. 121 */ getActiveStatistics()122 public BatteryStatsImpl getActiveStatistics() { 123 return mStats; 124 } 125 126 // These are for direct use by the activity manager... 127 addIsolatedUid(int isolatedUid, int appUid)128 void addIsolatedUid(int isolatedUid, int appUid) { 129 synchronized (mStats) { 130 mStats.addIsolatedUidLocked(isolatedUid, appUid); 131 } 132 } 133 removeIsolatedUid(int isolatedUid, int appUid)134 void removeIsolatedUid(int isolatedUid, int appUid) { 135 synchronized (mStats) { 136 mStats.removeIsolatedUidLocked(isolatedUid, appUid); 137 } 138 } 139 noteProcessStart(String name, int uid)140 void noteProcessStart(String name, int uid) { 141 synchronized (mStats) { 142 mStats.noteProcessStartLocked(name, uid); 143 } 144 } 145 noteProcessCrash(String name, int uid)146 void noteProcessCrash(String name, int uid) { 147 synchronized (mStats) { 148 mStats.noteProcessCrashLocked(name, uid); 149 } 150 } 151 noteProcessAnr(String name, int uid)152 void noteProcessAnr(String name, int uid) { 153 synchronized (mStats) { 154 mStats.noteProcessAnrLocked(name, uid); 155 } 156 } 157 noteProcessState(String name, int uid, int state)158 void noteProcessState(String name, int uid, int state) { 159 synchronized (mStats) { 160 mStats.noteProcessStateLocked(name, uid, state); 161 } 162 } 163 noteProcessFinish(String name, int uid)164 void noteProcessFinish(String name, int uid) { 165 synchronized (mStats) { 166 mStats.noteProcessFinishLocked(name, uid); 167 } 168 } 169 170 // Public interface... 171 getStatistics()172 public byte[] getStatistics() { 173 mContext.enforceCallingPermission( 174 android.Manifest.permission.BATTERY_STATS, null); 175 //Slog.i("foo", "SENDING BATTERY INFO:"); 176 //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM)); 177 Parcel out = Parcel.obtain(); 178 mStats.writeToParcel(out, 0); 179 byte[] data = out.marshall(); 180 out.recycle(); 181 return data; 182 } 183 getStatisticsStream()184 public ParcelFileDescriptor getStatisticsStream() { 185 mContext.enforceCallingPermission( 186 android.Manifest.permission.BATTERY_STATS, null); 187 //Slog.i("foo", "SENDING BATTERY INFO:"); 188 //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM)); 189 Parcel out = Parcel.obtain(); 190 mStats.writeToParcel(out, 0); 191 byte[] data = out.marshall(); 192 out.recycle(); 193 try { 194 return ParcelFileDescriptor.fromData(data, "battery-stats"); 195 } catch (IOException e) { 196 Slog.w(TAG, "Unable to create shared memory", e); 197 return null; 198 } 199 } 200 computeBatteryTimeRemaining()201 public long computeBatteryTimeRemaining() { 202 synchronized (mStats) { 203 long time = mStats.computeBatteryTimeRemaining(SystemClock.elapsedRealtime()); 204 return time >= 0 ? (time/1000) : time; 205 } 206 } 207 computeChargeTimeRemaining()208 public long computeChargeTimeRemaining() { 209 synchronized (mStats) { 210 long time = mStats.computeChargeTimeRemaining(SystemClock.elapsedRealtime()); 211 return time >= 0 ? (time/1000) : time; 212 } 213 } 214 noteEvent(int code, String name, int uid)215 public void noteEvent(int code, String name, int uid) { 216 enforceCallingPermission(); 217 synchronized (mStats) { 218 mStats.noteEventLocked(code, name, uid); 219 } 220 } 221 noteSyncStart(String name, int uid)222 public void noteSyncStart(String name, int uid) { 223 enforceCallingPermission(); 224 synchronized (mStats) { 225 mStats.noteSyncStartLocked(name, uid); 226 } 227 } 228 noteSyncFinish(String name, int uid)229 public void noteSyncFinish(String name, int uid) { 230 enforceCallingPermission(); 231 synchronized (mStats) { 232 mStats.noteSyncFinishLocked(name, uid); 233 } 234 } 235 noteJobStart(String name, int uid)236 public void noteJobStart(String name, int uid) { 237 enforceCallingPermission(); 238 synchronized (mStats) { 239 mStats.noteJobStartLocked(name, uid); 240 } 241 } 242 noteJobFinish(String name, int uid)243 public void noteJobFinish(String name, int uid) { 244 enforceCallingPermission(); 245 synchronized (mStats) { 246 mStats.noteJobFinishLocked(name, uid); 247 } 248 } 249 noteStartWakelock(int uid, int pid, String name, String historyName, int type, boolean unimportantForLogging)250 public void noteStartWakelock(int uid, int pid, String name, String historyName, int type, 251 boolean unimportantForLogging) { 252 enforceCallingPermission(); 253 synchronized (mStats) { 254 mStats.noteStartWakeLocked(uid, pid, name, historyName, type, unimportantForLogging, 255 SystemClock.elapsedRealtime(), SystemClock.uptimeMillis()); 256 } 257 } 258 noteStopWakelock(int uid, int pid, String name, String historyName, int type)259 public void noteStopWakelock(int uid, int pid, String name, String historyName, int type) { 260 enforceCallingPermission(); 261 synchronized (mStats) { 262 mStats.noteStopWakeLocked(uid, pid, name, historyName, type, 263 SystemClock.elapsedRealtime(), SystemClock.uptimeMillis()); 264 } 265 } 266 noteStartWakelockFromSource(WorkSource ws, int pid, String name, String historyName, int type, boolean unimportantForLogging)267 public void noteStartWakelockFromSource(WorkSource ws, int pid, String name, 268 String historyName, int type, boolean unimportantForLogging) { 269 enforceCallingPermission(); 270 synchronized (mStats) { 271 mStats.noteStartWakeFromSourceLocked(ws, pid, name, historyName, 272 type, unimportantForLogging); 273 } 274 } 275 noteChangeWakelockFromSource(WorkSource ws, int pid, String name, String historyName, int type, WorkSource newWs, int newPid, String newName, String newHistoryName, int newType, boolean newUnimportantForLogging)276 public void noteChangeWakelockFromSource(WorkSource ws, int pid, String name, 277 String historyName, int type, WorkSource newWs, int newPid, String newName, 278 String newHistoryName, int newType, boolean newUnimportantForLogging) { 279 enforceCallingPermission(); 280 synchronized (mStats) { 281 mStats.noteChangeWakelockFromSourceLocked(ws, pid, name, historyName, type, 282 newWs, newPid, newName, newHistoryName, newType, newUnimportantForLogging); 283 } 284 } 285 noteStopWakelockFromSource(WorkSource ws, int pid, String name, String historyName, int type)286 public void noteStopWakelockFromSource(WorkSource ws, int pid, String name, String historyName, 287 int type) { 288 enforceCallingPermission(); 289 synchronized (mStats) { 290 mStats.noteStopWakeFromSourceLocked(ws, pid, name, historyName, type); 291 } 292 } 293 noteStartSensor(int uid, int sensor)294 public void noteStartSensor(int uid, int sensor) { 295 enforceCallingPermission(); 296 synchronized (mStats) { 297 mStats.noteStartSensorLocked(uid, sensor); 298 } 299 } 300 noteStopSensor(int uid, int sensor)301 public void noteStopSensor(int uid, int sensor) { 302 enforceCallingPermission(); 303 synchronized (mStats) { 304 mStats.noteStopSensorLocked(uid, sensor); 305 } 306 } 307 noteVibratorOn(int uid, long durationMillis)308 public void noteVibratorOn(int uid, long durationMillis) { 309 enforceCallingPermission(); 310 synchronized (mStats) { 311 mStats.noteVibratorOnLocked(uid, durationMillis); 312 } 313 } 314 noteVibratorOff(int uid)315 public void noteVibratorOff(int uid) { 316 enforceCallingPermission(); 317 synchronized (mStats) { 318 mStats.noteVibratorOffLocked(uid); 319 } 320 } 321 noteStartGps(int uid)322 public void noteStartGps(int uid) { 323 enforceCallingPermission(); 324 synchronized (mStats) { 325 mStats.noteStartGpsLocked(uid); 326 } 327 } 328 noteStopGps(int uid)329 public void noteStopGps(int uid) { 330 enforceCallingPermission(); 331 synchronized (mStats) { 332 mStats.noteStopGpsLocked(uid); 333 } 334 } 335 noteScreenState(int state)336 public void noteScreenState(int state) { 337 enforceCallingPermission(); 338 synchronized (mStats) { 339 mStats.noteScreenStateLocked(state); 340 } 341 } 342 noteScreenBrightness(int brightness)343 public void noteScreenBrightness(int brightness) { 344 enforceCallingPermission(); 345 synchronized (mStats) { 346 mStats.noteScreenBrightnessLocked(brightness); 347 } 348 } 349 noteUserActivity(int uid, int event)350 public void noteUserActivity(int uid, int event) { 351 enforceCallingPermission(); 352 synchronized (mStats) { 353 mStats.noteUserActivityLocked(uid, event); 354 } 355 } 356 noteInteractive(boolean interactive)357 public void noteInteractive(boolean interactive) { 358 enforceCallingPermission(); 359 synchronized (mStats) { 360 mStats.noteInteractiveLocked(interactive); 361 } 362 } 363 noteConnectivityChanged(int type, String extra)364 public void noteConnectivityChanged(int type, String extra) { 365 enforceCallingPermission(); 366 synchronized (mStats) { 367 mStats.noteConnectivityChangedLocked(type, extra); 368 } 369 } 370 noteMobileRadioPowerState(int powerState, long timestampNs)371 public void noteMobileRadioPowerState(int powerState, long timestampNs) { 372 enforceCallingPermission(); 373 synchronized (mStats) { 374 mStats.noteMobileRadioPowerState(powerState, timestampNs); 375 } 376 } 377 notePhoneOn()378 public void notePhoneOn() { 379 enforceCallingPermission(); 380 synchronized (mStats) { 381 mStats.notePhoneOnLocked(); 382 } 383 } 384 notePhoneOff()385 public void notePhoneOff() { 386 enforceCallingPermission(); 387 synchronized (mStats) { 388 mStats.notePhoneOffLocked(); 389 } 390 } 391 notePhoneSignalStrength(SignalStrength signalStrength)392 public void notePhoneSignalStrength(SignalStrength signalStrength) { 393 enforceCallingPermission(); 394 synchronized (mStats) { 395 mStats.notePhoneSignalStrengthLocked(signalStrength); 396 } 397 } 398 notePhoneDataConnectionState(int dataType, boolean hasData)399 public void notePhoneDataConnectionState(int dataType, boolean hasData) { 400 enforceCallingPermission(); 401 synchronized (mStats) { 402 mStats.notePhoneDataConnectionStateLocked(dataType, hasData); 403 } 404 } 405 notePhoneState(int state)406 public void notePhoneState(int state) { 407 enforceCallingPermission(); 408 int simState = TelephonyManager.getDefault().getSimState(); 409 synchronized (mStats) { 410 mStats.notePhoneStateLocked(state, simState); 411 } 412 } 413 noteWifiOn()414 public void noteWifiOn() { 415 enforceCallingPermission(); 416 synchronized (mStats) { 417 mStats.noteWifiOnLocked(); 418 } 419 } 420 noteWifiOff()421 public void noteWifiOff() { 422 enforceCallingPermission(); 423 synchronized (mStats) { 424 mStats.noteWifiOffLocked(); 425 } 426 } 427 noteStartAudio(int uid)428 public void noteStartAudio(int uid) { 429 enforceCallingPermission(); 430 synchronized (mStats) { 431 mStats.noteAudioOnLocked(uid); 432 } 433 } 434 noteStopAudio(int uid)435 public void noteStopAudio(int uid) { 436 enforceCallingPermission(); 437 synchronized (mStats) { 438 mStats.noteAudioOffLocked(uid); 439 } 440 } 441 noteStartVideo(int uid)442 public void noteStartVideo(int uid) { 443 enforceCallingPermission(); 444 synchronized (mStats) { 445 mStats.noteVideoOnLocked(uid); 446 } 447 } 448 noteStopVideo(int uid)449 public void noteStopVideo(int uid) { 450 enforceCallingPermission(); 451 synchronized (mStats) { 452 mStats.noteVideoOffLocked(uid); 453 } 454 } 455 noteResetAudio()456 public void noteResetAudio() { 457 enforceCallingPermission(); 458 synchronized (mStats) { 459 mStats.noteResetAudioLocked(); 460 } 461 } 462 noteResetVideo()463 public void noteResetVideo() { 464 enforceCallingPermission(); 465 synchronized (mStats) { 466 mStats.noteResetVideoLocked(); 467 } 468 } 469 noteFlashlightOn()470 public void noteFlashlightOn() { 471 enforceCallingPermission(); 472 synchronized (mStats) { 473 mStats.noteFlashlightOnLocked(); 474 } 475 } 476 noteFlashlightOff()477 public void noteFlashlightOff() { 478 enforceCallingPermission(); 479 synchronized (mStats) { 480 mStats.noteFlashlightOffLocked(); 481 } 482 } 483 noteWifiRunning(WorkSource ws)484 public void noteWifiRunning(WorkSource ws) { 485 enforceCallingPermission(); 486 synchronized (mStats) { 487 mStats.noteWifiRunningLocked(ws); 488 } 489 } 490 noteWifiRunningChanged(WorkSource oldWs, WorkSource newWs)491 public void noteWifiRunningChanged(WorkSource oldWs, WorkSource newWs) { 492 enforceCallingPermission(); 493 synchronized (mStats) { 494 mStats.noteWifiRunningChangedLocked(oldWs, newWs); 495 } 496 } 497 noteWifiStopped(WorkSource ws)498 public void noteWifiStopped(WorkSource ws) { 499 enforceCallingPermission(); 500 synchronized (mStats) { 501 mStats.noteWifiStoppedLocked(ws); 502 } 503 } 504 noteWifiState(int wifiState, String accessPoint)505 public void noteWifiState(int wifiState, String accessPoint) { 506 enforceCallingPermission(); 507 synchronized (mStats) { 508 mStats.noteWifiStateLocked(wifiState, accessPoint); 509 } 510 } 511 noteWifiSupplicantStateChanged(int supplState, boolean failedAuth)512 public void noteWifiSupplicantStateChanged(int supplState, boolean failedAuth) { 513 enforceCallingPermission(); 514 synchronized (mStats) { 515 mStats.noteWifiSupplicantStateChangedLocked(supplState, failedAuth); 516 } 517 } 518 noteWifiRssiChanged(int newRssi)519 public void noteWifiRssiChanged(int newRssi) { 520 enforceCallingPermission(); 521 synchronized (mStats) { 522 mStats.noteWifiRssiChangedLocked(newRssi); 523 } 524 } 525 noteBluetoothOn()526 public void noteBluetoothOn() { 527 enforceCallingPermission(); 528 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 529 if (adapter != null) { 530 adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener, 531 BluetoothProfile.HEADSET); 532 } 533 synchronized (mStats) { 534 if (mBluetoothHeadset != null) { 535 mStats.noteBluetoothOnLocked(); 536 mStats.setBtHeadset(mBluetoothHeadset); 537 } else { 538 mBluetoothPendingStats = true; 539 } 540 } 541 } 542 543 private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener = 544 new BluetoothProfile.ServiceListener() { 545 public void onServiceConnected(int profile, BluetoothProfile proxy) { 546 mBluetoothHeadset = (BluetoothHeadset) proxy; 547 synchronized (mStats) { 548 if (mBluetoothPendingStats) { 549 mStats.noteBluetoothOnLocked(); 550 mStats.setBtHeadset(mBluetoothHeadset); 551 mBluetoothPendingStats = false; 552 } 553 } 554 } 555 556 public void onServiceDisconnected(int profile) { 557 mBluetoothHeadset = null; 558 } 559 }; 560 noteBluetoothOff()561 public void noteBluetoothOff() { 562 enforceCallingPermission(); 563 synchronized (mStats) { 564 mBluetoothPendingStats = false; 565 mStats.noteBluetoothOffLocked(); 566 } 567 } 568 noteBluetoothState(int bluetoothState)569 public void noteBluetoothState(int bluetoothState) { 570 enforceCallingPermission(); 571 synchronized (mStats) { 572 mStats.noteBluetoothStateLocked(bluetoothState); 573 } 574 } 575 noteFullWifiLockAcquired(int uid)576 public void noteFullWifiLockAcquired(int uid) { 577 enforceCallingPermission(); 578 synchronized (mStats) { 579 mStats.noteFullWifiLockAcquiredLocked(uid); 580 } 581 } 582 noteFullWifiLockReleased(int uid)583 public void noteFullWifiLockReleased(int uid) { 584 enforceCallingPermission(); 585 synchronized (mStats) { 586 mStats.noteFullWifiLockReleasedLocked(uid); 587 } 588 } 589 noteWifiScanStarted(int uid)590 public void noteWifiScanStarted(int uid) { 591 enforceCallingPermission(); 592 synchronized (mStats) { 593 mStats.noteWifiScanStartedLocked(uid); 594 } 595 } 596 noteWifiScanStopped(int uid)597 public void noteWifiScanStopped(int uid) { 598 enforceCallingPermission(); 599 synchronized (mStats) { 600 mStats.noteWifiScanStoppedLocked(uid); 601 } 602 } 603 noteWifiMulticastEnabled(int uid)604 public void noteWifiMulticastEnabled(int uid) { 605 enforceCallingPermission(); 606 synchronized (mStats) { 607 mStats.noteWifiMulticastEnabledLocked(uid); 608 } 609 } 610 noteWifiMulticastDisabled(int uid)611 public void noteWifiMulticastDisabled(int uid) { 612 enforceCallingPermission(); 613 synchronized (mStats) { 614 mStats.noteWifiMulticastDisabledLocked(uid); 615 } 616 } 617 noteFullWifiLockAcquiredFromSource(WorkSource ws)618 public void noteFullWifiLockAcquiredFromSource(WorkSource ws) { 619 enforceCallingPermission(); 620 synchronized (mStats) { 621 mStats.noteFullWifiLockAcquiredFromSourceLocked(ws); 622 } 623 } 624 noteFullWifiLockReleasedFromSource(WorkSource ws)625 public void noteFullWifiLockReleasedFromSource(WorkSource ws) { 626 enforceCallingPermission(); 627 synchronized (mStats) { 628 mStats.noteFullWifiLockReleasedFromSourceLocked(ws); 629 } 630 } 631 noteWifiScanStartedFromSource(WorkSource ws)632 public void noteWifiScanStartedFromSource(WorkSource ws) { 633 enforceCallingPermission(); 634 synchronized (mStats) { 635 mStats.noteWifiScanStartedFromSourceLocked(ws); 636 } 637 } 638 noteWifiScanStoppedFromSource(WorkSource ws)639 public void noteWifiScanStoppedFromSource(WorkSource ws) { 640 enforceCallingPermission(); 641 synchronized (mStats) { 642 mStats.noteWifiScanStoppedFromSourceLocked(ws); 643 } 644 } 645 noteWifiBatchedScanStartedFromSource(WorkSource ws, int csph)646 public void noteWifiBatchedScanStartedFromSource(WorkSource ws, int csph) { 647 enforceCallingPermission(); 648 synchronized (mStats) { 649 mStats.noteWifiBatchedScanStartedFromSourceLocked(ws, csph); 650 } 651 } 652 noteWifiBatchedScanStoppedFromSource(WorkSource ws)653 public void noteWifiBatchedScanStoppedFromSource(WorkSource ws) { 654 enforceCallingPermission(); 655 synchronized (mStats) { 656 mStats.noteWifiBatchedScanStoppedFromSourceLocked(ws); 657 } 658 } 659 noteWifiMulticastEnabledFromSource(WorkSource ws)660 public void noteWifiMulticastEnabledFromSource(WorkSource ws) { 661 enforceCallingPermission(); 662 synchronized (mStats) { 663 mStats.noteWifiMulticastEnabledFromSourceLocked(ws); 664 } 665 } 666 noteWifiMulticastDisabledFromSource(WorkSource ws)667 public void noteWifiMulticastDisabledFromSource(WorkSource ws) { 668 enforceCallingPermission(); 669 synchronized (mStats) { 670 mStats.noteWifiMulticastDisabledFromSourceLocked(ws); 671 } 672 } 673 674 @Override noteNetworkInterfaceType(String iface, int type)675 public void noteNetworkInterfaceType(String iface, int type) { 676 enforceCallingPermission(); 677 synchronized (mStats) { 678 mStats.noteNetworkInterfaceTypeLocked(iface, type); 679 } 680 } 681 682 @Override noteNetworkStatsEnabled()683 public void noteNetworkStatsEnabled() { 684 enforceCallingPermission(); 685 synchronized (mStats) { 686 mStats.noteNetworkStatsEnabledLocked(); 687 } 688 } 689 isOnBattery()690 public boolean isOnBattery() { 691 return mStats.isOnBattery(); 692 } 693 setBatteryState(int status, int health, int plugType, int level, int temp, int volt)694 public void setBatteryState(int status, int health, int plugType, int level, 695 int temp, int volt) { 696 enforceCallingPermission(); 697 mStats.setBatteryState(status, health, plugType, level, temp, volt); 698 } 699 getAwakeTimeBattery()700 public long getAwakeTimeBattery() { 701 mContext.enforceCallingOrSelfPermission( 702 android.Manifest.permission.BATTERY_STATS, null); 703 return mStats.getAwakeTimeBattery(); 704 } 705 getAwakeTimePlugged()706 public long getAwakeTimePlugged() { 707 mContext.enforceCallingOrSelfPermission( 708 android.Manifest.permission.BATTERY_STATS, null); 709 return mStats.getAwakeTimePlugged(); 710 } 711 enforceCallingPermission()712 public void enforceCallingPermission() { 713 if (Binder.getCallingPid() == Process.myPid()) { 714 return; 715 } 716 mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS, 717 Binder.getCallingPid(), Binder.getCallingUid(), null); 718 } 719 720 final class WakeupReasonThread extends Thread { 721 final int[] mIrqs = new int[32]; 722 final String[] mReasons = new String[32]; 723 WakeupReasonThread()724 WakeupReasonThread() { 725 super("BatteryStats_wakeupReason"); 726 } 727 run()728 public void run() { 729 Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND); 730 731 try { 732 int num; 733 while ((num=nativeWaitWakeup(mIrqs, mReasons)) >= 0) { 734 synchronized (mStats) { 735 if (num > 0) { 736 for (int i=0; i<num; i++) { 737 mStats.noteWakeupReasonLocked(mReasons[i]); 738 } 739 } else { 740 mStats.noteWakeupReasonLocked("unknown"); 741 } 742 } 743 } 744 } catch (RuntimeException e) { 745 Slog.e(TAG, "Failure reading wakeup reasons", e); 746 } 747 } 748 } 749 nativeWaitWakeup(int[] outIrqs, String[] outReasons)750 private static native int nativeWaitWakeup(int[] outIrqs, String[] outReasons); 751 dumpHelp(PrintWriter pw)752 private void dumpHelp(PrintWriter pw) { 753 pw.println("Battery stats (batterystats) dump options:"); 754 pw.println(" [--checkin] [--history] [--history-start] [--unplugged] [--charged] [-c]"); 755 pw.println(" [--reset] [--write] [-h] [<package.name>]"); 756 pw.println(" --checkin: format output for a checkin report."); 757 pw.println(" --history: show only history data."); 758 pw.println(" --history-start <num>: show only history data starting at given time offset."); 759 pw.println(" --unplugged: only output data since last unplugged."); 760 pw.println(" --charged: only output data since last charged."); 761 pw.println(" --reset: reset the stats, clearing all current data."); 762 pw.println(" --write: force write current collected stats to disk."); 763 pw.println(" <package.name>: optional name of package to filter output by."); 764 pw.println(" -h: print this help text."); 765 pw.println("Battery stats (batterystats) commands:"); 766 pw.println(" enable|disable <option>"); 767 pw.println(" Enable or disable a running option. Option state is not saved across boots."); 768 pw.println(" Options are:"); 769 pw.println(" full-history: include additional detailed events in battery history:"); 770 pw.println(" wake_lock_in and proc events"); 771 pw.println(" no-auto-reset: don't automatically reset stats when unplugged"); 772 } 773 doEnableOrDisable(PrintWriter pw, int i, String[] args, boolean enable)774 private int doEnableOrDisable(PrintWriter pw, int i, String[] args, boolean enable) { 775 i++; 776 if (i >= args.length) { 777 pw.println("Missing option argument for " + (enable ? "--enable" : "--disable")); 778 dumpHelp(pw); 779 return -1; 780 } 781 if ("full-wake-history".equals(args[i]) || "full-history".equals(args[i])) { 782 synchronized (mStats) { 783 mStats.setRecordAllHistoryLocked(enable); 784 } 785 } else if ("no-auto-reset".equals(args[i])) { 786 synchronized (mStats) { 787 mStats.setNoAutoReset(enable); 788 } 789 } else { 790 pw.println("Unknown enable/disable option: " + args[i]); 791 dumpHelp(pw); 792 return -1; 793 } 794 return i; 795 } 796 797 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)798 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 799 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 800 != PackageManager.PERMISSION_GRANTED) { 801 pw.println("Permission Denial: can't dump BatteryStats from from pid=" 802 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 803 + " without permission " + android.Manifest.permission.DUMP); 804 return; 805 } 806 807 int flags = 0; 808 boolean useCheckinFormat = false; 809 boolean isRealCheckin = false; 810 boolean noOutput = false; 811 boolean writeData = false; 812 long historyStart = -1; 813 int reqUid = -1; 814 if (args != null) { 815 for (int i=0; i<args.length; i++) { 816 String arg = args[i]; 817 if ("--checkin".equals(arg)) { 818 useCheckinFormat = true; 819 isRealCheckin = true; 820 } else if ("--history".equals(arg)) { 821 flags |= BatteryStats.DUMP_HISTORY_ONLY; 822 } else if ("--history-start".equals(arg)) { 823 flags |= BatteryStats.DUMP_HISTORY_ONLY; 824 i++; 825 if (i >= args.length) { 826 pw.println("Missing time argument for --history-since"); 827 dumpHelp(pw); 828 return; 829 } 830 historyStart = Long.parseLong(args[i]); 831 writeData = true; 832 } else if ("-c".equals(arg)) { 833 useCheckinFormat = true; 834 flags |= BatteryStats.DUMP_INCLUDE_HISTORY; 835 } else if ("--unplugged".equals(arg)) { 836 flags |= BatteryStats.DUMP_UNPLUGGED_ONLY; 837 } else if ("--charged".equals(arg)) { 838 flags |= BatteryStats.DUMP_CHARGED_ONLY; 839 } else if ("--reset".equals(arg)) { 840 synchronized (mStats) { 841 mStats.resetAllStatsCmdLocked(); 842 pw.println("Battery stats reset."); 843 noOutput = true; 844 } 845 } else if ("--write".equals(arg)) { 846 synchronized (mStats) { 847 mStats.writeSyncLocked(); 848 pw.println("Battery stats written."); 849 noOutput = true; 850 } 851 } else if ("--enable".equals(arg) || "enable".equals(arg)) { 852 i = doEnableOrDisable(pw, i, args, true); 853 if (i < 0) { 854 return; 855 } 856 pw.println("Enabled: " + args[i]); 857 return; 858 } else if ("--disable".equals(arg) || "disable".equals(arg)) { 859 i = doEnableOrDisable(pw, i, args, false); 860 if (i < 0) { 861 return; 862 } 863 pw.println("Disabled: " + args[i]); 864 return; 865 } else if ("-h".equals(arg)) { 866 dumpHelp(pw); 867 return; 868 } else if ("-a".equals(arg)) { 869 flags |= BatteryStats.DUMP_VERBOSE; 870 } else if (arg.length() > 0 && arg.charAt(0) == '-'){ 871 pw.println("Unknown option: " + arg); 872 dumpHelp(pw); 873 return; 874 } else { 875 // Not an option, last argument must be a package name. 876 try { 877 reqUid = mContext.getPackageManager().getPackageUid(arg, 878 UserHandle.getCallingUserId()); 879 } catch (PackageManager.NameNotFoundException e) { 880 pw.println("Unknown package: " + arg); 881 dumpHelp(pw); 882 return; 883 } 884 } 885 } 886 } 887 if (noOutput) { 888 return; 889 } 890 if (BatteryStatsHelper.checkWifiOnly(mContext)) { 891 flags |= BatteryStats.DUMP_DEVICE_WIFI_ONLY; 892 } 893 if (reqUid >= 0) { 894 // By default, if the caller is only interested in a specific package, then 895 // we only dump the aggregated data since charged. 896 if ((flags&(BatteryStats.DUMP_HISTORY_ONLY|BatteryStats.DUMP_UNPLUGGED_ONLY 897 |BatteryStats.DUMP_CHARGED_ONLY)) == 0) { 898 flags |= BatteryStats.DUMP_CHARGED_ONLY; 899 // Also if they are doing -c, we don't want history. 900 flags &= ~BatteryStats.DUMP_INCLUDE_HISTORY; 901 } 902 } 903 if (useCheckinFormat) { 904 List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(0); 905 if (isRealCheckin) { 906 // For a real checkin, first we want to prefer to use the last complete checkin 907 // file if there is one. 908 synchronized (mStats.mCheckinFile) { 909 if (mStats.mCheckinFile.exists()) { 910 try { 911 byte[] raw = mStats.mCheckinFile.readFully(); 912 if (raw != null) { 913 Parcel in = Parcel.obtain(); 914 in.unmarshall(raw, 0, raw.length); 915 in.setDataPosition(0); 916 BatteryStatsImpl checkinStats = new BatteryStatsImpl( 917 null, mStats.mHandler); 918 checkinStats.readSummaryFromParcel(in); 919 in.recycle(); 920 checkinStats.dumpCheckinLocked(mContext, pw, apps, flags, 921 historyStart); 922 mStats.mCheckinFile.delete(); 923 return; 924 } 925 } catch (IOException e) { 926 Slog.w(TAG, "Failure reading checkin file " 927 + mStats.mCheckinFile.getBaseFile(), e); 928 } 929 } 930 } 931 } 932 synchronized (mStats) { 933 mStats.dumpCheckinLocked(mContext, pw, apps, flags, historyStart); 934 if (writeData) { 935 mStats.writeAsyncLocked(); 936 } 937 } 938 } else { 939 synchronized (mStats) { 940 mStats.dumpLocked(mContext, pw, flags, reqUid, historyStart); 941 if (writeData) { 942 mStats.writeAsyncLocked(); 943 } 944 } 945 } 946 } 947 } 948