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