private void handleRemoveListener(int uid) { synchronized (mListeners) { if (mClientUids.indexOfKey(uid) < 0) { // Shouldn't be here -- don't have this uid. Log.w(TAG, "Unneeded remove listener for uid " + uid); return; } mClientUids.delete(uid); if (mNavigating) { try { mBatteryStats.noteStopGps(uid); } catch (RemoteException e) { Log.w(TAG, "RemoteException in removeListener"); } } } }
private void handleAddListener(int uid) { synchronized (mListeners) { if (mClientUids.indexOfKey(uid) >= 0) { // Shouldn't be here -- already have this uid. Log.w(TAG, "Duplicate add listener for uid " + uid); return; } mClientUids.put(uid, 0); if (mNavigating) { try { mBatteryStats.noteStartGps(uid); } catch (RemoteException e) { Log.w(TAG, "RemoteException in addListener"); } } } }
/** called from native code to update our status */ private void reportStatus(int status) { if (VERBOSE) Log.v(TAG, "reportStatus status: " + status); synchronized (mListeners) { boolean wasNavigating = mNavigating; switch (status) { case GPS_STATUS_SESSION_BEGIN: mNavigating = true; mEngineOn = true; break; case GPS_STATUS_SESSION_END: mNavigating = false; break; case GPS_STATUS_ENGINE_ON: mEngineOn = true; break; case GPS_STATUS_ENGINE_OFF: mEngineOn = false; mNavigating = false; break; } // beware, the events can come out of order if ((mNavigating || mEngineOn) && !mWakeLock.isHeld()) { if (DEBUG) Log.d(TAG, "Acquiring wakelock"); mWakeLock.acquire(); } if (wasNavigating != mNavigating) { int size = mListeners.size(); for (int i = 0; i < size; i++) { Listener listener = mListeners.get(i); try { if (mNavigating) { listener.mListener.onGpsStarted(); } else { listener.mListener.onGpsStopped(); } } catch (RemoteException e) { Log.w(TAG, "RemoteException in reportStatus"); mListeners.remove(listener); // adjust for size of list changing size--; } } try { // update battery stats for (int i = mClientUids.size() - 1; i >= 0; i--) { int uid = mClientUids.keyAt(i); if (mNavigating) { mBatteryStats.noteStartGps(uid); } else { mBatteryStats.noteStopGps(uid); } } } catch (RemoteException e) { Log.w(TAG, "RemoteException in reportStatus"); } // send an intent to notify that the GPS has been enabled or disabled. Intent intent = new Intent(GPS_ENABLED_CHANGE_ACTION); intent.putExtra(EXTRA_ENABLED, mNavigating); mContext.sendBroadcast(intent); } // beware, the events can come out of order if (!mNavigating && !mEngineOn && mWakeLock.isHeld()) { if (DEBUG) Log.d(TAG, "Releasing wakelock"); mWakeLock.release(); } } }
private void processValuesLocked() { boolean logOutlier = false; long dischargeDuration = 0; mBatteryLevelCritical = (mBatteryProps.batteryLevel <= mCriticalBatteryLevel); if (mBatteryProps.chargerAcOnline) { mPlugType = BatteryManager.BATTERY_PLUGGED_AC; } else if (mBatteryProps.chargerUsbOnline) { mPlugType = BatteryManager.BATTERY_PLUGGED_USB; } else if (mBatteryProps.chargerWirelessOnline) { mPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS; } else { mPlugType = BATTERY_PLUGGED_NONE; } if (DEBUG) { Slog.d( TAG, "Processing new values: " + "chargerAcOnline=" + mBatteryProps.chargerAcOnline + ", chargerUsbOnline=" + mBatteryProps.chargerUsbOnline + ", chargerWirelessOnline=" + mBatteryProps.chargerWirelessOnline + ", batteryStatus=" + mBatteryProps.batteryStatus + ", batteryHealth=" + mBatteryProps.batteryHealth + ", batteryPresent=" + mBatteryProps.batteryPresent + ", batteryLevel=" + mBatteryProps.batteryLevel + ", batteryTechnology=" + mBatteryProps.batteryTechnology + ", batteryVoltage=" + mBatteryProps.batteryVoltage + ", batteryCurrentNow=" + mBatteryProps.batteryCurrentNow + ", batteryChargeCounter=" + mBatteryProps.batteryChargeCounter + ", batteryTemperature=" + mBatteryProps.batteryTemperature + ", mBatteryLevelCritical=" + mBatteryLevelCritical + ", mPlugType=" + mPlugType); } if (mLastBatteryVoltage != mBatteryProps.batteryVoltage) { Xlog.d( TAG, "mBatteryVoltage=" + mBatteryProps.batteryVoltage + ", batteryLevel=" + mBatteryProps.batteryLevel_2nd); } // Update the battery LED mLed.updateLightsLocked(); // Let the battery stats keep track of the current level. try { mBatteryStats.setBatteryState( mBatteryProps.batteryStatus, mBatteryProps.batteryHealth, mPlugType, mBatteryProps.batteryLevel, mBatteryProps.batteryTemperature, mBatteryProps.batteryVoltage); } catch (RemoteException e) { // Should never happen. } shutdownIfNoPowerLocked(); shutdownIfOverTempLocked(); if (mBatteryProps.batteryStatus != mLastBatteryStatus || mBatteryProps.batteryStatus_2nd != mLastBatteryStatus_2nd || mBatteryProps.batteryHealth != mLastBatteryHealth || mBatteryProps.batteryPresent != mLastBatteryPresent || mBatteryProps.batteryPresent_2nd != mLastBatteryPresent_2nd || mBatteryProps.batteryLevel != mLastBatteryLevel || mBatteryProps.batteryLevel_2nd != mLastBatteryLevel_2nd || mPlugType != mLastPlugType || mBatteryProps.batteryVoltage != mLastBatteryVoltage || mBatteryProps.batteryTemperature != mLastBatteryTemperature || mInvalidCharger != mLastInvalidCharger) { if (mPlugType != mLastPlugType) { if (mLastPlugType == BATTERY_PLUGGED_NONE) { // discharging -> charging // There's no value in this data unless we've discharged at least once and the // battery level has changed; so don't log until it does. if (mDischargeStartTime != 0 && mDischargeStartLevel != mBatteryProps.batteryLevel) { dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime; logOutlier = true; EventLog.writeEvent( EventLogTags.BATTERY_DISCHARGE, dischargeDuration, mDischargeStartLevel, mBatteryProps.batteryLevel); // make sure we see a discharge event before logging again mDischargeStartTime = 0; } } else if (mPlugType == BATTERY_PLUGGED_NONE) { // charging -> discharging or we just powered up mDischargeStartTime = SystemClock.elapsedRealtime(); mDischargeStartLevel = mBatteryProps.batteryLevel; } } if (mBatteryProps.batteryStatus != mLastBatteryStatus || mBatteryProps.batteryHealth != mLastBatteryHealth || mBatteryProps.batteryPresent != mLastBatteryPresent || mPlugType != mLastPlugType) { EventLog.writeEvent( EventLogTags.BATTERY_STATUS, mBatteryProps.batteryStatus, mBatteryProps.batteryHealth, mBatteryProps.batteryPresent ? 1 : 0, mPlugType, mBatteryProps.batteryTechnology); } if (mBatteryProps.batteryLevel != mLastBatteryLevel) { // Don't do this just from voltage or temperature changes, that is // too noisy. EventLog.writeEvent( EventLogTags.BATTERY_LEVEL, mBatteryProps.batteryLevel, mBatteryProps.batteryVoltage, mBatteryProps.batteryTemperature); } if (mBatteryLevelCritical && !mLastBatteryLevelCritical && mPlugType == BATTERY_PLUGGED_NONE) { // We want to make sure we log discharge cycle outliers // if the battery is about to die. dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime; logOutlier = true; } final boolean plugged = mPlugType != BATTERY_PLUGGED_NONE; final boolean oldPlugged = mLastPlugType != BATTERY_PLUGGED_NONE; /* The ACTION_BATTERY_LOW broadcast is sent in these situations: * - is just un-plugged (previously was plugged) and battery level is * less than or equal to WARNING, or * - is not plugged and battery level falls to WARNING boundary * (becomes <= mLowBatteryWarningLevel). */ final boolean sendBatteryLow = !plugged && mBatteryProps.batteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN && mBatteryProps.batteryLevel <= mLowBatteryWarningLevel && (oldPlugged || mLastBatteryLevel > mLowBatteryWarningLevel); sendIntentLocked(); // Separate broadcast is sent for power connected / not connected // since the standard intent will not wake any applications and some // applications may want to have smart behavior based on this. if (mPlugType != 0 && mLastPlugType == 0) { mHandler.post( new Runnable() { @Override public void run() { Intent statusIntent = new Intent(Intent.ACTION_POWER_CONNECTED); statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL); } }); } else if (mPlugType == 0 && mLastPlugType != 0) { mHandler.post( new Runnable() { @Override public void run() { Intent statusIntent = new Intent(Intent.ACTION_POWER_DISCONNECTED); statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL); } }); } if (sendBatteryLow) { mSentLowBatteryBroadcast = true; mHandler.post( new Runnable() { @Override public void run() { Intent statusIntent = new Intent(Intent.ACTION_BATTERY_LOW); statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL); } }); } else if (mSentLowBatteryBroadcast && mLastBatteryLevel >= mLowBatteryCloseWarningLevel) { mSentLowBatteryBroadcast = false; mHandler.post( new Runnable() { @Override public void run() { Intent statusIntent = new Intent(Intent.ACTION_BATTERY_OKAY); statusIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL); } }); } // Update the battery LED // mLed.updateLightsLocked(); // This needs to be done after sendIntent() so that we get the lastest battery stats. if (logOutlier && dischargeDuration != 0) { logOutlierLocked(dischargeDuration); } mLastBatteryStatus = mBatteryProps.batteryStatus; mLastBatteryStatus_2nd = mBatteryProps.batteryStatus_2nd; mLastBatteryHealth = mBatteryProps.batteryHealth; mLastBatteryPresent = mBatteryProps.batteryPresent; mLastBatteryPresent_2nd = mBatteryProps.batteryPresent_2nd; mLastBatteryLevel = mBatteryProps.batteryLevel; mLastBatteryLevel_2nd = mBatteryProps.batteryLevel_2nd; mLastPlugType = mPlugType; mLastBatteryVoltage = mBatteryProps.batteryVoltage; mLastBatteryTemperature = mBatteryProps.batteryTemperature; mLastBatteryLevelCritical = mBatteryLevelCritical; mLastInvalidCharger = mInvalidCharger; } }