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