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