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 noteStartGps(int uid) { 148 enforceCallingPermission(); 149 synchronized (mStats) { 150 mStats.noteStartGpsLocked(uid); 151 } 152 } 153 154 public void noteStopGps(int uid) { 155 enforceCallingPermission(); 156 synchronized (mStats) { 157 mStats.noteStopGpsLocked(uid); 158 } 159 } 160 161 public void noteScreenOn() { 162 enforceCallingPermission(); 163 synchronized (mStats) { 164 mStats.noteScreenOnLocked(); 165 } 166 } 167 168 public void noteScreenBrightness(int brightness) { 169 enforceCallingPermission(); 170 synchronized (mStats) { 171 mStats.noteScreenBrightnessLocked(brightness); 172 } 173 } 174 175 public void noteScreenOff() { 176 enforceCallingPermission(); 177 synchronized (mStats) { 178 mStats.noteScreenOffLocked(); 179 } 180 } 181 182 public void noteInputEvent() { 183 enforceCallingPermission(); 184 mStats.noteInputEventAtomic(); 185 } 186 187 public void noteUserActivity(int uid, int event) { 188 enforceCallingPermission(); 189 synchronized (mStats) { 190 mStats.noteUserActivityLocked(uid, event); 191 } 192 } 193 194 public void notePhoneOn() { 195 enforceCallingPermission(); 196 synchronized (mStats) { 197 mStats.notePhoneOnLocked(); 198 } 199 } 200 201 public void notePhoneOff() { 202 enforceCallingPermission(); 203 synchronized (mStats) { 204 mStats.notePhoneOffLocked(); 205 } 206 } 207 208 public void notePhoneSignalStrength(SignalStrength signalStrength) { 209 enforceCallingPermission(); 210 synchronized (mStats) { 211 mStats.notePhoneSignalStrengthLocked(signalStrength); 212 } 213 } 214 215 public void notePhoneDataConnectionState(int dataType, boolean hasData) { 216 enforceCallingPermission(); 217 synchronized (mStats) { 218 mStats.notePhoneDataConnectionStateLocked(dataType, hasData); 219 } 220 } 221 222 public void notePhoneState(int state) { 223 enforceCallingPermission(); 224 int simState = TelephonyManager.getDefault().getSimState(); 225 synchronized (mStats) { 226 mStats.notePhoneStateLocked(state, simState); 227 } 228 } 229 230 public void noteWifiOn() { 231 enforceCallingPermission(); 232 synchronized (mStats) { 233 mStats.noteWifiOnLocked(); 234 } 235 } 236 237 public void noteWifiOff() { 238 enforceCallingPermission(); 239 synchronized (mStats) { 240 mStats.noteWifiOffLocked(); 241 } 242 } 243 244 public void noteStartAudio(int uid) { 245 enforceCallingPermission(); 246 synchronized (mStats) { 247 mStats.noteAudioOnLocked(uid); 248 } 249 } 250 251 public void noteStopAudio(int uid) { 252 enforceCallingPermission(); 253 synchronized (mStats) { 254 mStats.noteAudioOffLocked(uid); 255 } 256 } 257 258 public void noteStartVideo(int uid) { 259 enforceCallingPermission(); 260 synchronized (mStats) { 261 mStats.noteVideoOnLocked(uid); 262 } 263 } 264 265 public void noteStopVideo(int uid) { 266 enforceCallingPermission(); 267 synchronized (mStats) { 268 mStats.noteVideoOffLocked(uid); 269 } 270 } 271 272 public void noteWifiRunning(WorkSource ws) { 273 enforceCallingPermission(); 274 synchronized (mStats) { 275 mStats.noteWifiRunningLocked(ws); 276 } 277 } 278 279 public void noteWifiRunningChanged(WorkSource oldWs, WorkSource newWs) { 280 enforceCallingPermission(); 281 synchronized (mStats) { 282 mStats.noteWifiRunningChangedLocked(oldWs, newWs); 283 } 284 } 285 286 public void noteWifiStopped(WorkSource ws) { 287 enforceCallingPermission(); 288 synchronized (mStats) { 289 mStats.noteWifiStoppedLocked(ws); 290 } 291 } 292 293 public void noteBluetoothOn() { 294 enforceCallingPermission(); 295 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 296 if (adapter != null) { 297 adapter.getProfileProxy(mContext, mBluetoothProfileServiceListener, 298 BluetoothProfile.HEADSET); 299 } 300 synchronized (mStats) { 301 if (mBluetoothHeadset != null) { 302 mStats.noteBluetoothOnLocked(); 303 mStats.setBtHeadset(mBluetoothHeadset); 304 } else { 305 mBluetoothPendingStats = true; 306 } 307 } 308 } 309 310 private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener = 311 new BluetoothProfile.ServiceListener() { 312 public void onServiceConnected(int profile, BluetoothProfile proxy) { 313 mBluetoothHeadset = (BluetoothHeadset) proxy; 314 synchronized (mStats) { 315 if (mBluetoothPendingStats) { 316 mStats.noteBluetoothOnLocked(); 317 mStats.setBtHeadset(mBluetoothHeadset); 318 mBluetoothPendingStats = false; 319 } 320 } 321 } 322 323 public void onServiceDisconnected(int profile) { 324 mBluetoothHeadset = null; 325 } 326 }; 327 328 public void noteBluetoothOff() { 329 enforceCallingPermission(); 330 synchronized (mStats) { 331 mBluetoothPendingStats = false; 332 mStats.noteBluetoothOffLocked(); 333 } 334 } 335 336 public void noteFullWifiLockAcquired(int uid) { 337 enforceCallingPermission(); 338 synchronized (mStats) { 339 mStats.noteFullWifiLockAcquiredLocked(uid); 340 } 341 } 342 343 public void noteFullWifiLockReleased(int uid) { 344 enforceCallingPermission(); 345 synchronized (mStats) { 346 mStats.noteFullWifiLockReleasedLocked(uid); 347 } 348 } 349 350 public void noteScanWifiLockAcquired(int uid) { 351 enforceCallingPermission(); 352 synchronized (mStats) { 353 mStats.noteScanWifiLockAcquiredLocked(uid); 354 } 355 } 356 357 public void noteScanWifiLockReleased(int uid) { 358 enforceCallingPermission(); 359 synchronized (mStats) { 360 mStats.noteScanWifiLockReleasedLocked(uid); 361 } 362 } 363 364 public void noteWifiMulticastEnabled(int uid) { 365 enforceCallingPermission(); 366 synchronized (mStats) { 367 mStats.noteWifiMulticastEnabledLocked(uid); 368 } 369 } 370 371 public void noteWifiMulticastDisabled(int uid) { 372 enforceCallingPermission(); 373 synchronized (mStats) { 374 mStats.noteWifiMulticastDisabledLocked(uid); 375 } 376 } 377 378 public void noteFullWifiLockAcquiredFromSource(WorkSource ws) { 379 enforceCallingPermission(); 380 synchronized (mStats) { 381 mStats.noteFullWifiLockAcquiredFromSourceLocked(ws); 382 } 383 } 384 385 public void noteFullWifiLockReleasedFromSource(WorkSource ws) { 386 enforceCallingPermission(); 387 synchronized (mStats) { 388 mStats.noteFullWifiLockReleasedFromSourceLocked(ws); 389 } 390 } 391 392 public void noteScanWifiLockAcquiredFromSource(WorkSource ws) { 393 enforceCallingPermission(); 394 synchronized (mStats) { 395 mStats.noteScanWifiLockAcquiredFromSourceLocked(ws); 396 } 397 } 398 399 public void noteScanWifiLockReleasedFromSource(WorkSource ws) { 400 enforceCallingPermission(); 401 synchronized (mStats) { 402 mStats.noteScanWifiLockReleasedFromSourceLocked(ws); 403 } 404 } 405 406 public void noteWifiMulticastEnabledFromSource(WorkSource ws) { 407 enforceCallingPermission(); 408 synchronized (mStats) { 409 mStats.noteWifiMulticastEnabledFromSourceLocked(ws); 410 } 411 } 412 413 public void noteWifiMulticastDisabledFromSource(WorkSource ws) { 414 enforceCallingPermission(); 415 synchronized (mStats) { 416 mStats.noteWifiMulticastDisabledFromSourceLocked(ws); 417 } 418 } 419 420 public void noteNetworkInterfaceType(String iface, int type) { 421 enforceCallingPermission(); 422 synchronized (mStats) { 423 mStats.noteNetworkInterfaceTypeLocked(iface, type); 424 } 425 } 426 427 public boolean isOnBattery() { 428 return mStats.isOnBattery(); 429 } 430 431 public void setBatteryState(int status, int health, int plugType, int level, 432 int temp, int volt) { 433 enforceCallingPermission(); 434 mStats.setBatteryState(status, health, plugType, level, temp, volt); 435 } 436 437 public long getAwakeTimeBattery() { 438 mContext.enforceCallingOrSelfPermission( 439 android.Manifest.permission.BATTERY_STATS, null); 440 return mStats.getAwakeTimeBattery(); 441 } 442 443 public long getAwakeTimePlugged() { 444 mContext.enforceCallingOrSelfPermission( 445 android.Manifest.permission.BATTERY_STATS, null); 446 return mStats.getAwakeTimePlugged(); 447 } 448 449 public void enforceCallingPermission() { 450 if (Binder.getCallingPid() == Process.myPid()) { 451 return; 452 } 453 mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS, 454 Binder.getCallingPid(), Binder.getCallingUid(), null); 455 } 456 457 private void dumpHelp(PrintWriter pw) { 458 pw.println("Battery stats (batteryinfo) dump options:"); 459 pw.println(" [--checkin] [--reset] [--write] [-h]"); 460 pw.println(" --checkin: format output for a checkin report."); 461 pw.println(" --reset: reset the stats, clearing all current data."); 462 pw.println(" --write: force write current collected stats to disk."); 463 pw.println(" -h: print this help text."); 464 } 465 466 @Override 467 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 468 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 469 != PackageManager.PERMISSION_GRANTED) { 470 pw.println("Permission Denial: can't dump BatteryStats from from pid=" 471 + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 472 + " without permission " + android.Manifest.permission.DUMP); 473 return; 474 } 475 476 boolean isCheckin = false; 477 boolean noOutput = false; 478 if (args != null) { 479 for (String arg : args) { 480 if ("--checkin".equals(arg)) { 481 isCheckin = true; 482 } else if ("--reset".equals(arg)) { 483 synchronized (mStats) { 484 mStats.resetAllStatsLocked(); 485 pw.println("Battery stats reset."); 486 noOutput = true; 487 } 488 } else if ("--write".equals(arg)) { 489 synchronized (mStats) { 490 mStats.writeSyncLocked(); 491 pw.println("Battery stats written."); 492 noOutput = true; 493 } 494 } else if ("-h".equals(arg)) { 495 dumpHelp(pw); 496 return; 497 } else if ("-a".equals(arg)) { 498 // fall through 499 } else { 500 pw.println("Unknown option: " + arg); 501 dumpHelp(pw); 502 } 503 } 504 } 505 if (noOutput) { 506 return; 507 } 508 if (isCheckin) { 509 List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(0); 510 synchronized (mStats) { 511 mStats.dumpCheckinLocked(pw, args, apps); 512 } 513 } else { 514 synchronized (mStats) { 515 mStats.dumpLocked(pw); 516 } 517 } 518 } 519 } 520