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