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