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