BatteryStatsService.java revision e95c3cd89591ba586aa8a0f7a17660c6fb8770bc
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 noteScreenState(int state) { 234 enforceCallingPermission(); 235 synchronized (mStats) { 236 mStats.noteScreenStateLocked(state); 237 } 238 } 239 240 public void noteScreenBrightness(int brightness) { 241 enforceCallingPermission(); 242 synchronized (mStats) { 243 mStats.noteScreenBrightnessLocked(brightness); 244 } 245 } 246 247 public void noteUserActivity(int uid, int event) { 248 enforceCallingPermission(); 249 synchronized (mStats) { 250 mStats.noteUserActivityLocked(uid, event); 251 } 252 } 253 254 public void noteInteractive(boolean interactive) { 255 enforceCallingPermission(); 256 synchronized (mStats) { 257 mStats.noteInteractiveLocked(interactive); 258 } 259 } 260 261 public void noteMobileRadioPowerState(int powerState, long timestampNs) { 262 enforceCallingPermission(); 263 synchronized (mStats) { 264 mStats.noteMobileRadioPowerState(powerState, timestampNs); 265 } 266 } 267 268 public void notePhoneOn() { 269 enforceCallingPermission(); 270 synchronized (mStats) { 271 mStats.notePhoneOnLocked(); 272 } 273 } 274 275 public void notePhoneOff() { 276 enforceCallingPermission(); 277 synchronized (mStats) { 278 mStats.notePhoneOffLocked(); 279 } 280 } 281 282 public void notePhoneSignalStrength(SignalStrength signalStrength) { 283 enforceCallingPermission(); 284 synchronized (mStats) { 285 mStats.notePhoneSignalStrengthLocked(signalStrength); 286 } 287 } 288 289 public void notePhoneDataConnectionState(int dataType, boolean hasData) { 290 enforceCallingPermission(); 291 synchronized (mStats) { 292 mStats.notePhoneDataConnectionStateLocked(dataType, hasData); 293 } 294 } 295 296 public void notePhoneState(int state) { 297 enforceCallingPermission(); 298 int simState = TelephonyManager.getDefault().getSimState(); 299 synchronized (mStats) { 300 mStats.notePhoneStateLocked(state, simState); 301 } 302 } 303 304 public void noteWifiOn() { 305 enforceCallingPermission(); 306 synchronized (mStats) { 307 mStats.noteWifiOnLocked(); 308 } 309 } 310 311 public void noteWifiOff() { 312 enforceCallingPermission(); 313 synchronized (mStats) { 314 mStats.noteWifiOffLocked(); 315 } 316 } 317 318 public void noteStartAudio(int uid) { 319 enforceCallingPermission(); 320 synchronized (mStats) { 321 mStats.noteAudioOnLocked(uid); 322 } 323 } 324 325 public void noteStopAudio(int uid) { 326 enforceCallingPermission(); 327 synchronized (mStats) { 328 mStats.noteAudioOffLocked(uid); 329 } 330 } 331 332 public void noteStartVideo(int uid) { 333 enforceCallingPermission(); 334 synchronized (mStats) { 335 mStats.noteVideoOnLocked(uid); 336 } 337 } 338 339 public void noteStopVideo(int uid) { 340 enforceCallingPermission(); 341 synchronized (mStats) { 342 mStats.noteVideoOffLocked(uid); 343 } 344 } 345 346 public void noteWifiRunning(WorkSource ws) { 347 enforceCallingPermission(); 348 synchronized (mStats) { 349 mStats.noteWifiRunningLocked(ws); 350 } 351 } 352 353 public void noteWifiRunningChanged(WorkSource oldWs, WorkSource newWs) { 354 enforceCallingPermission(); 355 synchronized (mStats) { 356 mStats.noteWifiRunningChangedLocked(oldWs, newWs); 357 } 358 } 359 360 public void noteWifiStopped(WorkSource ws) { 361 enforceCallingPermission(); 362 synchronized (mStats) { 363 mStats.noteWifiStoppedLocked(ws); 364 } 365 } 366 367 public void noteWifiState(int wifiState, String accessPoint) { 368 enforceCallingPermission(); 369 synchronized (mStats) { 370 mStats.noteWifiStateLocked(wifiState, accessPoint); 371 } 372 } 373 374 public void noteBluetoothOn() { 375 enforceCallingPermission(); 376 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 377 if (adapter != null) { 378 adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener, 379 BluetoothProfile.HEADSET); 380 } 381 synchronized (mStats) { 382 if (mBluetoothHeadset != null) { 383 mStats.noteBluetoothOnLocked(); 384 mStats.setBtHeadset(mBluetoothHeadset); 385 } else { 386 mBluetoothPendingStats = true; 387 } 388 } 389 } 390 391 private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener = 392 new BluetoothProfile.ServiceListener() { 393 public void onServiceConnected(int profile, BluetoothProfile proxy) { 394 mBluetoothHeadset = (BluetoothHeadset) proxy; 395 synchronized (mStats) { 396 if (mBluetoothPendingStats) { 397 mStats.noteBluetoothOnLocked(); 398 mStats.setBtHeadset(mBluetoothHeadset); 399 mBluetoothPendingStats = false; 400 } 401 } 402 } 403 404 public void onServiceDisconnected(int profile) { 405 mBluetoothHeadset = null; 406 } 407 }; 408 409 public void noteBluetoothOff() { 410 enforceCallingPermission(); 411 synchronized (mStats) { 412 mBluetoothPendingStats = false; 413 mStats.noteBluetoothOffLocked(); 414 } 415 } 416 417 public void noteBluetoothState(int bluetoothState) { 418 enforceCallingPermission(); 419 synchronized (mStats) { 420 mStats.noteBluetoothStateLocked(bluetoothState); 421 } 422 } 423 424 public void noteFullWifiLockAcquired(int uid) { 425 enforceCallingPermission(); 426 synchronized (mStats) { 427 mStats.noteFullWifiLockAcquiredLocked(uid); 428 } 429 } 430 431 public void noteFullWifiLockReleased(int uid) { 432 enforceCallingPermission(); 433 synchronized (mStats) { 434 mStats.noteFullWifiLockReleasedLocked(uid); 435 } 436 } 437 438 public void noteWifiScanStarted(int uid) { 439 enforceCallingPermission(); 440 synchronized (mStats) { 441 mStats.noteWifiScanStartedLocked(uid); 442 } 443 } 444 445 public void noteWifiScanStopped(int uid) { 446 enforceCallingPermission(); 447 synchronized (mStats) { 448 mStats.noteWifiScanStoppedLocked(uid); 449 } 450 } 451 452 public void noteWifiMulticastEnabled(int uid) { 453 enforceCallingPermission(); 454 synchronized (mStats) { 455 mStats.noteWifiMulticastEnabledLocked(uid); 456 } 457 } 458 459 public void noteWifiMulticastDisabled(int uid) { 460 enforceCallingPermission(); 461 synchronized (mStats) { 462 mStats.noteWifiMulticastDisabledLocked(uid); 463 } 464 } 465 466 public void noteFullWifiLockAcquiredFromSource(WorkSource ws) { 467 enforceCallingPermission(); 468 synchronized (mStats) { 469 mStats.noteFullWifiLockAcquiredFromSourceLocked(ws); 470 } 471 } 472 473 public void noteFullWifiLockReleasedFromSource(WorkSource ws) { 474 enforceCallingPermission(); 475 synchronized (mStats) { 476 mStats.noteFullWifiLockReleasedFromSourceLocked(ws); 477 } 478 } 479 480 public void noteWifiScanStartedFromSource(WorkSource ws) { 481 enforceCallingPermission(); 482 synchronized (mStats) { 483 mStats.noteWifiScanStartedFromSourceLocked(ws); 484 } 485 } 486 487 public void noteWifiScanStoppedFromSource(WorkSource ws) { 488 enforceCallingPermission(); 489 synchronized (mStats) { 490 mStats.noteWifiScanStoppedFromSourceLocked(ws); 491 } 492 } 493 494 public void noteWifiBatchedScanStartedFromSource(WorkSource ws, int csph) { 495 enforceCallingPermission(); 496 synchronized (mStats) { 497 mStats.noteWifiBatchedScanStartedFromSourceLocked(ws, csph); 498 } 499 } 500 501 public void noteWifiBatchedScanStoppedFromSource(WorkSource ws) { 502 enforceCallingPermission(); 503 synchronized (mStats) { 504 mStats.noteWifiBatchedScanStoppedFromSourceLocked(ws); 505 } 506 } 507 508 public void noteWifiMulticastEnabledFromSource(WorkSource ws) { 509 enforceCallingPermission(); 510 synchronized (mStats) { 511 mStats.noteWifiMulticastEnabledFromSourceLocked(ws); 512 } 513 } 514 515 public void noteWifiMulticastDisabledFromSource(WorkSource ws) { 516 enforceCallingPermission(); 517 synchronized (mStats) { 518 mStats.noteWifiMulticastDisabledFromSourceLocked(ws); 519 } 520 } 521 522 @Override 523 public void noteNetworkInterfaceType(String iface, int type) { 524 enforceCallingPermission(); 525 synchronized (mStats) { 526 mStats.noteNetworkInterfaceTypeLocked(iface, type); 527 } 528 } 529 530 @Override 531 public void noteNetworkStatsEnabled() { 532 enforceCallingPermission(); 533 synchronized (mStats) { 534 mStats.noteNetworkStatsEnabledLocked(); 535 } 536 } 537 538 public boolean isOnBattery() { 539 return mStats.isOnBattery(); 540 } 541 542 public void setBatteryState(int status, int health, int plugType, int level, 543 int temp, int volt) { 544 enforceCallingPermission(); 545 mStats.setBatteryState(status, health, plugType, level, temp, volt); 546 } 547 548 public long getAwakeTimeBattery() { 549 mContext.enforceCallingOrSelfPermission( 550 android.Manifest.permission.BATTERY_STATS, null); 551 return mStats.getAwakeTimeBattery(); 552 } 553 554 public long getAwakeTimePlugged() { 555 mContext.enforceCallingOrSelfPermission( 556 android.Manifest.permission.BATTERY_STATS, null); 557 return mStats.getAwakeTimePlugged(); 558 } 559 560 public void enforceCallingPermission() { 561 if (Binder.getCallingPid() == Process.myPid()) { 562 return; 563 } 564 mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS, 565 Binder.getCallingPid(), Binder.getCallingUid(), null); 566 } 567 568 final class WakeupReasonThread extends Thread { 569 final int[] mIrqs = new int[32]; 570 final String[] mReasons = new String[32]; 571 572 WakeupReasonThread() { 573 super("BatteryStats_wakeupReason"); 574 } 575 576 public void run() { 577 Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND); 578 579 try { 580 int num; 581 while ((num=nativeWaitWakeup(mIrqs, mReasons)) >= 0) { 582 synchronized (mStats) { 583 if (num > 0) { 584 for (int i=0; i<num; i++) { 585 mStats.noteWakeupReasonLocked(mReasons[i]); 586 } 587 } else { 588 mStats.noteWakeupReasonLocked("unknown"); 589 } 590 } 591 } 592 } catch (RuntimeException e) { 593 Slog.e(TAG, "Failure reading wakeup reasons", e); 594 } 595 } 596 } 597 598 private static native int nativeWaitWakeup(int[] outIrqs, String[] outReasons); 599 600 private void dumpHelp(PrintWriter pw) { 601 pw.println("Battery stats (batterystats) dump options:"); 602 pw.println(" [--checkin] [--history] [--history-start] [--unplugged] [--charged] [-c]"); 603 pw.println(" [--reset] [--write] [-h] [<package.name>]"); 604 pw.println(" --checkin: format output for a checkin report."); 605 pw.println(" --history: show only history data."); 606 pw.println(" --history-start <num>: show only history data starting at given time offset."); 607 pw.println(" --unplugged: only output data since last unplugged."); 608 pw.println(" --charged: only output data since last charged."); 609 pw.println(" --reset: reset the stats, clearing all current data."); 610 pw.println(" --write: force write current collected stats to disk."); 611 pw.println(" -h: print this help text."); 612 pw.println(" <package.name>: optional name of package to filter output by."); 613 } 614 615 @Override 616 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 617 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 618 != PackageManager.PERMISSION_GRANTED) { 619 pw.println("Permission Denial: can't dump BatteryStats from from pid=" 620 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 621 + " without permission " + android.Manifest.permission.DUMP); 622 return; 623 } 624 625 int flags = 0; 626 boolean isCheckin = false; 627 boolean noOutput = false; 628 long historyStart = -1; 629 int reqUid = -1; 630 if (args != null) { 631 for (int i=0; i<args.length; i++) { 632 String arg = args[i]; 633 if ("--checkin".equals(arg)) { 634 isCheckin = true; 635 } else if ("--history".equals(arg)) { 636 flags |= BatteryStats.DUMP_HISTORY_ONLY; 637 } else if ("--history-start".equals(arg)) { 638 flags |= BatteryStats.DUMP_HISTORY_ONLY; 639 i++; 640 if (i >= args.length) { 641 pw.println("Missing time argument for --history-since"); 642 dumpHelp(pw); 643 return; 644 } 645 historyStart = Long.parseLong(args[i]); 646 } else if ("-c".equals(arg)) { 647 isCheckin = true; 648 flags |= BatteryStats.DUMP_INCLUDE_HISTORY; 649 } else if ("--unplugged".equals(arg)) { 650 flags |= BatteryStats.DUMP_UNPLUGGED_ONLY; 651 } else if ("--charged".equals(arg)) { 652 flags |= BatteryStats.DUMP_CHARGED_ONLY; 653 } else if ("--reset".equals(arg)) { 654 synchronized (mStats) { 655 mStats.resetAllStatsCmdLocked(); 656 pw.println("Battery stats reset."); 657 noOutput = true; 658 } 659 } else if ("--write".equals(arg)) { 660 synchronized (mStats) { 661 mStats.writeSyncLocked(); 662 pw.println("Battery stats written."); 663 noOutput = true; 664 } 665 } else if ("-h".equals(arg)) { 666 dumpHelp(pw); 667 return; 668 } else if ("-a".equals(arg)) { 669 flags |= BatteryStats.DUMP_VERBOSE; 670 } else if (arg.length() > 0 && arg.charAt(0) == '-'){ 671 pw.println("Unknown option: " + arg); 672 dumpHelp(pw); 673 return; 674 } else { 675 // Not an option, last argument must be a package name. 676 try { 677 reqUid = mContext.getPackageManager().getPackageUid(arg, 678 UserHandle.getCallingUserId()); 679 } catch (PackageManager.NameNotFoundException e) { 680 pw.println("Unknown package: " + arg); 681 dumpHelp(pw); 682 return; 683 } 684 } 685 } 686 } 687 if (noOutput) { 688 return; 689 } 690 if (isCheckin) { 691 List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(0); 692 synchronized (mStats) { 693 mStats.dumpCheckinLocked(mContext, pw, apps, flags, historyStart); 694 } 695 } else { 696 synchronized (mStats) { 697 mStats.dumpLocked(mContext, pw, flags, reqUid, historyStart); 698 } 699 } 700 } 701} 702