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