BatteryStatsService.java revision ab5c0ea43cf457b20ab4267a14b224f39e0511bf
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 17package com.android.server.am; 18 19import android.bluetooth.BluetoothAdapter; 20import android.bluetooth.BluetoothHeadset; 21import android.bluetooth.BluetoothProfile; 22import android.content.Context; 23import android.content.pm.ApplicationInfo; 24import android.content.pm.PackageManager; 25import android.os.BatteryStats; 26import android.os.Binder; 27import android.os.Handler; 28import android.os.IBinder; 29import android.os.Parcel; 30import android.os.Process; 31import android.os.ServiceManager; 32import android.os.SystemClock; 33import android.os.UserHandle; 34import android.os.WorkSource; 35import android.telephony.DataConnectionRealTimeInfo; 36import android.telephony.SignalStrength; 37import android.telephony.TelephonyManager; 38import android.util.Slog; 39 40import com.android.internal.app.IBatteryStats; 41import com.android.internal.os.BatteryStatsImpl; 42import com.android.internal.os.PowerProfile; 43 44import java.io.FileDescriptor; 45import java.io.PrintWriter; 46import java.util.List; 47 48/** 49 * All information we are collecting about things that can happen that impact 50 * battery life. 51 */ 52public final class BatteryStatsService extends IBatteryStats.Stub { 53 static final String TAG = "BatteryStatsService"; 54 55 static IBatteryStats sService; 56 57 final BatteryStatsImpl mStats; 58 Context mContext; 59 private boolean mBluetoothPendingStats; 60 private BluetoothHeadset mBluetoothHeadset; 61 62 BatteryStatsService(String filename, Handler handler) { 63 mStats = new BatteryStatsImpl(filename, handler); 64 } 65 66 public void publish(Context context) { 67 mContext = context; 68 ServiceManager.addService(BatteryStats.SERVICE_NAME, asBinder()); 69 mStats.setNumSpeedSteps(new PowerProfile(mContext).getNumSpeedSteps()); 70 mStats.setRadioScanningTimeout(mContext.getResources().getInteger( 71 com.android.internal.R.integer.config_radioScanningTimeout) 72 * 1000L); 73 (new WakeupReasonThread()).start(); 74 } 75 76 public void shutdown() { 77 Slog.w("BatteryStats", "Writing battery stats before shutdown..."); 78 synchronized (mStats) { 79 mStats.shutdownLocked(); 80 } 81 } 82 83 public static IBatteryStats getService() { 84 if (sService != null) { 85 return sService; 86 } 87 IBinder b = ServiceManager.getService(BatteryStats.SERVICE_NAME); 88 sService = asInterface(b); 89 return sService; 90 } 91 92 /** 93 * @return the current statistics object, which may be modified 94 * to reflect events that affect battery usage. You must lock the 95 * stats object before doing anything with it. 96 */ 97 public BatteryStatsImpl getActiveStatistics() { 98 return mStats; 99 } 100 101 public byte[] getStatistics() { 102 mContext.enforceCallingPermission( 103 android.Manifest.permission.BATTERY_STATS, null); 104 //Slog.i("foo", "SENDING BATTERY INFO:"); 105 //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM)); 106 Parcel out = Parcel.obtain(); 107 mStats.writeToParcel(out, 0); 108 byte[] data = out.marshall(); 109 out.recycle(); 110 return data; 111 } 112 113 public long computeBatteryTimeRemaining() { 114 synchronized (mStats) { 115 long time = mStats.computeBatteryTimeRemaining(SystemClock.elapsedRealtime()); 116 return time >= 0 ? (time/1000) : time; 117 } 118 } 119 120 public long computeChargeTimeRemaining() { 121 synchronized (mStats) { 122 long time = mStats.computeChargeTimeRemaining(SystemClock.elapsedRealtime()); 123 return time >= 0 ? (time/1000) : time; 124 } 125 } 126 127 public void addIsolatedUid(int isolatedUid, int appUid) { 128 enforceCallingPermission(); 129 synchronized (mStats) { 130 mStats.addIsolatedUidLocked(isolatedUid, appUid); 131 } 132 } 133 134 public void removeIsolatedUid(int isolatedUid, int appUid) { 135 enforceCallingPermission(); 136 synchronized (mStats) { 137 mStats.removeIsolatedUidLocked(isolatedUid, appUid); 138 } 139 } 140 141 public void noteEvent(int code, String name, int uid) { 142 enforceCallingPermission(); 143 synchronized (mStats) { 144 mStats.noteEventLocked(code, name, uid); 145 } 146 } 147 148 public void noteStartWakelock(int uid, int pid, String name, String historyName, int type, 149 boolean unimportantForLogging) { 150 enforceCallingPermission(); 151 synchronized (mStats) { 152 mStats.noteStartWakeLocked(uid, pid, name, historyName, type, unimportantForLogging, 153 SystemClock.elapsedRealtime(), SystemClock.uptimeMillis()); 154 } 155 } 156 157 public void noteStopWakelock(int uid, int pid, String name, int type) { 158 enforceCallingPermission(); 159 synchronized (mStats) { 160 mStats.noteStopWakeLocked(uid, pid, name, type, SystemClock.elapsedRealtime(), 161 SystemClock.uptimeMillis()); 162 } 163 } 164 165 public void noteStartWakelockFromSource(WorkSource ws, int pid, String name, 166 String historyName, int type, boolean unimportantForLogging) { 167 enforceCallingPermission(); 168 synchronized (mStats) { 169 mStats.noteStartWakeFromSourceLocked(ws, pid, name, historyName, 170 type, unimportantForLogging); 171 } 172 } 173 174 public void noteChangeWakelockFromSource(WorkSource ws, int pid, String name, int type, 175 WorkSource newWs, int newPid, String newName, 176 String newHistoryName, int newType, boolean newUnimportantForLogging) { 177 enforceCallingPermission(); 178 synchronized (mStats) { 179 mStats.noteChangeWakelockFromSourceLocked(ws, pid, name, type, 180 newWs, newPid, newName, newHistoryName, newType, newUnimportantForLogging); 181 } 182 } 183 184 public void noteStopWakelockFromSource(WorkSource ws, int pid, String name, int type) { 185 enforceCallingPermission(); 186 synchronized (mStats) { 187 mStats.noteStopWakeFromSourceLocked(ws, pid, name, type); 188 } 189 } 190 191 public void noteStartSensor(int uid, int sensor) { 192 enforceCallingPermission(); 193 synchronized (mStats) { 194 mStats.noteStartSensorLocked(uid, sensor); 195 } 196 } 197 198 public void noteStopSensor(int uid, int sensor) { 199 enforceCallingPermission(); 200 synchronized (mStats) { 201 mStats.noteStopSensorLocked(uid, sensor); 202 } 203 } 204 205 public void noteVibratorOn(int uid, long durationMillis) { 206 enforceCallingPermission(); 207 synchronized (mStats) { 208 mStats.noteVibratorOnLocked(uid, durationMillis); 209 } 210 } 211 212 public void noteVibratorOff(int uid) { 213 enforceCallingPermission(); 214 synchronized (mStats) { 215 mStats.noteVibratorOffLocked(uid); 216 } 217 } 218 219 public void noteStartGps(int uid) { 220 enforceCallingPermission(); 221 synchronized (mStats) { 222 mStats.noteStartGpsLocked(uid); 223 } 224 } 225 226 public void noteStopGps(int uid) { 227 enforceCallingPermission(); 228 synchronized (mStats) { 229 mStats.noteStopGpsLocked(uid); 230 } 231 } 232 233 public void noteScreenOn() { 234 enforceCallingPermission(); 235 synchronized (mStats) { 236 mStats.noteScreenOnLocked(); 237 } 238 } 239 240 public void noteScreenBrightness(int brightness) { 241 enforceCallingPermission(); 242 synchronized (mStats) { 243 mStats.noteScreenBrightnessLocked(brightness); 244 } 245 } 246 247 public void noteScreenOff() { 248 enforceCallingPermission(); 249 synchronized (mStats) { 250 mStats.noteScreenOffLocked(); 251 } 252 } 253 254 public void noteInputEvent() { 255 enforceCallingPermission(); 256 mStats.noteInputEventAtomic(); 257 } 258 259 public void noteUserActivity(int uid, int event) { 260 enforceCallingPermission(); 261 synchronized (mStats) { 262 mStats.noteUserActivityLocked(uid, event); 263 } 264 } 265 266 public void noteMobileRadioPowerState(int powerState, long timestampNs) { 267 enforceCallingPermission(); 268 synchronized (mStats) { 269 mStats.noteMobileRadioPowerState(powerState, timestampNs); 270 } 271 } 272 273 public void notePhoneOn() { 274 enforceCallingPermission(); 275 synchronized (mStats) { 276 mStats.notePhoneOnLocked(); 277 } 278 } 279 280 public void notePhoneOff() { 281 enforceCallingPermission(); 282 synchronized (mStats) { 283 mStats.notePhoneOffLocked(); 284 } 285 } 286 287 public void notePhoneSignalStrength(SignalStrength signalStrength) { 288 enforceCallingPermission(); 289 synchronized (mStats) { 290 mStats.notePhoneSignalStrengthLocked(signalStrength); 291 } 292 } 293 294 public void notePhoneDataConnectionState(int dataType, boolean hasData) { 295 enforceCallingPermission(); 296 synchronized (mStats) { 297 mStats.notePhoneDataConnectionStateLocked(dataType, hasData); 298 } 299 } 300 301 public void notePhoneState(int state) { 302 enforceCallingPermission(); 303 int simState = TelephonyManager.getDefault().getSimState(); 304 synchronized (mStats) { 305 mStats.notePhoneStateLocked(state, simState); 306 } 307 } 308 309 public void noteWifiOn() { 310 enforceCallingPermission(); 311 synchronized (mStats) { 312 mStats.noteWifiOnLocked(); 313 } 314 } 315 316 public void noteWifiOff() { 317 enforceCallingPermission(); 318 synchronized (mStats) { 319 mStats.noteWifiOffLocked(); 320 } 321 } 322 323 public void noteStartAudio(int uid) { 324 enforceCallingPermission(); 325 synchronized (mStats) { 326 mStats.noteAudioOnLocked(uid); 327 } 328 } 329 330 public void noteStopAudio(int uid) { 331 enforceCallingPermission(); 332 synchronized (mStats) { 333 mStats.noteAudioOffLocked(uid); 334 } 335 } 336 337 public void noteStartVideo(int uid) { 338 enforceCallingPermission(); 339 synchronized (mStats) { 340 mStats.noteVideoOnLocked(uid); 341 } 342 } 343 344 public void noteStopVideo(int uid) { 345 enforceCallingPermission(); 346 synchronized (mStats) { 347 mStats.noteVideoOffLocked(uid); 348 } 349 } 350 351 public void noteWifiRunning(WorkSource ws) { 352 enforceCallingPermission(); 353 synchronized (mStats) { 354 mStats.noteWifiRunningLocked(ws); 355 } 356 } 357 358 public void noteWifiRunningChanged(WorkSource oldWs, WorkSource newWs) { 359 enforceCallingPermission(); 360 synchronized (mStats) { 361 mStats.noteWifiRunningChangedLocked(oldWs, newWs); 362 } 363 } 364 365 public void noteWifiStopped(WorkSource ws) { 366 enforceCallingPermission(); 367 synchronized (mStats) { 368 mStats.noteWifiStoppedLocked(ws); 369 } 370 } 371 372 public void noteWifiState(int wifiState, String accessPoint) { 373 enforceCallingPermission(); 374 synchronized (mStats) { 375 mStats.noteWifiStateLocked(wifiState, accessPoint); 376 } 377 } 378 379 public void noteBluetoothOn() { 380 enforceCallingPermission(); 381 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 382 if (adapter != null) { 383 adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener, 384 BluetoothProfile.HEADSET); 385 } 386 synchronized (mStats) { 387 if (mBluetoothHeadset != null) { 388 mStats.noteBluetoothOnLocked(); 389 mStats.setBtHeadset(mBluetoothHeadset); 390 } else { 391 mBluetoothPendingStats = true; 392 } 393 } 394 } 395 396 private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener = 397 new BluetoothProfile.ServiceListener() { 398 public void onServiceConnected(int profile, BluetoothProfile proxy) { 399 mBluetoothHeadset = (BluetoothHeadset) proxy; 400 synchronized (mStats) { 401 if (mBluetoothPendingStats) { 402 mStats.noteBluetoothOnLocked(); 403 mStats.setBtHeadset(mBluetoothHeadset); 404 mBluetoothPendingStats = false; 405 } 406 } 407 } 408 409 public void onServiceDisconnected(int profile) { 410 mBluetoothHeadset = null; 411 } 412 }; 413 414 public void noteBluetoothOff() { 415 enforceCallingPermission(); 416 synchronized (mStats) { 417 mBluetoothPendingStats = false; 418 mStats.noteBluetoothOffLocked(); 419 } 420 } 421 422 public void noteBluetoothState(int bluetoothState) { 423 enforceCallingPermission(); 424 synchronized (mStats) { 425 mStats.noteBluetoothStateLocked(bluetoothState); 426 } 427 } 428 429 public void noteFullWifiLockAcquired(int uid) { 430 enforceCallingPermission(); 431 synchronized (mStats) { 432 mStats.noteFullWifiLockAcquiredLocked(uid); 433 } 434 } 435 436 public void noteFullWifiLockReleased(int uid) { 437 enforceCallingPermission(); 438 synchronized (mStats) { 439 mStats.noteFullWifiLockReleasedLocked(uid); 440 } 441 } 442 443 public void noteWifiScanStarted(int uid) { 444 enforceCallingPermission(); 445 synchronized (mStats) { 446 mStats.noteWifiScanStartedLocked(uid); 447 } 448 } 449 450 public void noteWifiScanStopped(int uid) { 451 enforceCallingPermission(); 452 synchronized (mStats) { 453 mStats.noteWifiScanStoppedLocked(uid); 454 } 455 } 456 457 public void noteWifiMulticastEnabled(int uid) { 458 enforceCallingPermission(); 459 synchronized (mStats) { 460 mStats.noteWifiMulticastEnabledLocked(uid); 461 } 462 } 463 464 public void noteWifiMulticastDisabled(int uid) { 465 enforceCallingPermission(); 466 synchronized (mStats) { 467 mStats.noteWifiMulticastDisabledLocked(uid); 468 } 469 } 470 471 public void noteFullWifiLockAcquiredFromSource(WorkSource ws) { 472 enforceCallingPermission(); 473 synchronized (mStats) { 474 mStats.noteFullWifiLockAcquiredFromSourceLocked(ws); 475 } 476 } 477 478 public void noteFullWifiLockReleasedFromSource(WorkSource ws) { 479 enforceCallingPermission(); 480 synchronized (mStats) { 481 mStats.noteFullWifiLockReleasedFromSourceLocked(ws); 482 } 483 } 484 485 public void noteWifiScanStartedFromSource(WorkSource ws) { 486 enforceCallingPermission(); 487 synchronized (mStats) { 488 mStats.noteWifiScanStartedFromSourceLocked(ws); 489 } 490 } 491 492 public void noteWifiScanStoppedFromSource(WorkSource ws) { 493 enforceCallingPermission(); 494 synchronized (mStats) { 495 mStats.noteWifiScanStoppedFromSourceLocked(ws); 496 } 497 } 498 499 public void noteWifiBatchedScanStartedFromSource(WorkSource ws, int csph) { 500 enforceCallingPermission(); 501 synchronized (mStats) { 502 mStats.noteWifiBatchedScanStartedFromSourceLocked(ws, csph); 503 } 504 } 505 506 public void noteWifiBatchedScanStoppedFromSource(WorkSource ws) { 507 enforceCallingPermission(); 508 synchronized (mStats) { 509 mStats.noteWifiBatchedScanStoppedFromSourceLocked(ws); 510 } 511 } 512 513 public void noteWifiMulticastEnabledFromSource(WorkSource ws) { 514 enforceCallingPermission(); 515 synchronized (mStats) { 516 mStats.noteWifiMulticastEnabledFromSourceLocked(ws); 517 } 518 } 519 520 public void noteWifiMulticastDisabledFromSource(WorkSource ws) { 521 enforceCallingPermission(); 522 synchronized (mStats) { 523 mStats.noteWifiMulticastDisabledFromSourceLocked(ws); 524 } 525 } 526 527 @Override 528 public void noteNetworkInterfaceType(String iface, int type) { 529 enforceCallingPermission(); 530 synchronized (mStats) { 531 mStats.noteNetworkInterfaceTypeLocked(iface, type); 532 } 533 } 534 535 @Override 536 public void noteNetworkStatsEnabled() { 537 enforceCallingPermission(); 538 synchronized (mStats) { 539 mStats.noteNetworkStatsEnabledLocked(); 540 } 541 } 542 543 public boolean isOnBattery() { 544 return mStats.isOnBattery(); 545 } 546 547 public void setBatteryState(int status, int health, int plugType, int level, 548 int temp, int volt) { 549 enforceCallingPermission(); 550 mStats.setBatteryState(status, health, plugType, level, temp, volt); 551 } 552 553 public long getAwakeTimeBattery() { 554 mContext.enforceCallingOrSelfPermission( 555 android.Manifest.permission.BATTERY_STATS, null); 556 return mStats.getAwakeTimeBattery(); 557 } 558 559 public long getAwakeTimePlugged() { 560 mContext.enforceCallingOrSelfPermission( 561 android.Manifest.permission.BATTERY_STATS, null); 562 return mStats.getAwakeTimePlugged(); 563 } 564 565 public void enforceCallingPermission() { 566 if (Binder.getCallingPid() == Process.myPid()) { 567 return; 568 } 569 mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS, 570 Binder.getCallingPid(), Binder.getCallingUid(), null); 571 } 572 573 final class WakeupReasonThread extends Thread { 574 final int[] mIrqs = new int[32]; 575 final String[] mReasons = new String[32]; 576 577 WakeupReasonThread() { 578 super("BatteryStats_wakeupReason"); 579 } 580 581 public void run() { 582 Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND); 583 584 try { 585 int num; 586 while ((num=nativeWaitWakeup(mIrqs, mReasons)) >= 0) { 587 synchronized (mStats) { 588 if (num > 0) { 589 for (int i=0; i<num; i++) { 590 mStats.noteWakeupReasonLocked(mReasons[i]); 591 } 592 } else { 593 mStats.noteWakeupReasonLocked("unknown"); 594 } 595 } 596 } 597 } catch (RuntimeException e) { 598 Slog.e(TAG, "Failure reading wakeup reasons", e); 599 } 600 } 601 } 602 603 private static native int nativeWaitWakeup(int[] outIrqs, String[] outReasons); 604 605 private void dumpHelp(PrintWriter pw) { 606 pw.println("Battery stats (batterystats) dump options:"); 607 pw.println(" [--checkin] [--history] [--history-start] [--unplugged] [--charged] [-c]"); 608 pw.println(" [--reset] [--write] [-h] [<package.name>]"); 609 pw.println(" --checkin: format output for a checkin report."); 610 pw.println(" --history: show only history data."); 611 pw.println(" --history-start <num>: show only history data starting at given time offset."); 612 pw.println(" --unplugged: only output data since last unplugged."); 613 pw.println(" --charged: only output data since last charged."); 614 pw.println(" --reset: reset the stats, clearing all current data."); 615 pw.println(" --write: force write current collected stats to disk."); 616 pw.println(" -h: print this help text."); 617 pw.println(" <package.name>: optional name of package to filter output by."); 618 } 619 620 @Override 621 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 622 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 623 != PackageManager.PERMISSION_GRANTED) { 624 pw.println("Permission Denial: can't dump BatteryStats from from pid=" 625 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 626 + " without permission " + android.Manifest.permission.DUMP); 627 return; 628 } 629 630 int flags = 0; 631 boolean isCheckin = false; 632 boolean noOutput = false; 633 long historyStart = -1; 634 int reqUid = -1; 635 if (args != null) { 636 for (int i=0; i<args.length; i++) { 637 String arg = args[i]; 638 if ("--checkin".equals(arg)) { 639 isCheckin = true; 640 } else if ("--history".equals(arg)) { 641 flags |= BatteryStats.DUMP_HISTORY_ONLY; 642 } else if ("--history-start".equals(arg)) { 643 flags |= BatteryStats.DUMP_HISTORY_ONLY; 644 i++; 645 if (i >= args.length) { 646 pw.println("Missing time argument for --history-since"); 647 dumpHelp(pw); 648 return; 649 } 650 historyStart = Long.parseLong(args[i]); 651 } else if ("-c".equals(arg)) { 652 isCheckin = true; 653 flags |= BatteryStats.DUMP_INCLUDE_HISTORY; 654 } else if ("--unplugged".equals(arg)) { 655 flags |= BatteryStats.DUMP_UNPLUGGED_ONLY; 656 } else if ("--charged".equals(arg)) { 657 flags |= BatteryStats.DUMP_CHARGED_ONLY; 658 } else if ("--reset".equals(arg)) { 659 synchronized (mStats) { 660 mStats.resetAllStatsCmdLocked(); 661 pw.println("Battery stats reset."); 662 noOutput = true; 663 } 664 } else if ("--write".equals(arg)) { 665 synchronized (mStats) { 666 mStats.writeSyncLocked(); 667 pw.println("Battery stats written."); 668 noOutput = true; 669 } 670 } else if ("-h".equals(arg)) { 671 dumpHelp(pw); 672 return; 673 } else if ("-a".equals(arg)) { 674 flags |= BatteryStats.DUMP_VERBOSE; 675 } else if (arg.length() > 0 && arg.charAt(0) == '-'){ 676 pw.println("Unknown option: " + arg); 677 dumpHelp(pw); 678 return; 679 } else { 680 // Not an option, last argument must be a package name. 681 try { 682 reqUid = mContext.getPackageManager().getPackageUid(arg, 683 UserHandle.getCallingUserId()); 684 } catch (PackageManager.NameNotFoundException e) { 685 pw.println("Unknown package: " + arg); 686 dumpHelp(pw); 687 return; 688 } 689 } 690 } 691 } 692 if (noOutput) { 693 return; 694 } 695 if (isCheckin) { 696 List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(0); 697 synchronized (mStats) { 698 mStats.dumpCheckinLocked(mContext, pw, apps, flags, historyStart); 699 } 700 } else { 701 synchronized (mStats) { 702 mStats.dumpLocked(mContext, pw, flags, reqUid, historyStart); 703 } 704 } 705 } 706} 707