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