// Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.firebase.crashlytics.internal.common; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.BatteryManager; /** A utility class representing the state of the battery. */ class BatteryState { static final int VELOCITY_UNPLUGGED = 1; static final int VELOCITY_CHARGING = 2; static final int VELOCITY_FULL = 3; private final Float level; private final boolean powerConnected; private BatteryState(Float level, boolean powerConnected) { this.powerConnected = powerConnected; this.level = level; } boolean isPowerConnected() { return powerConnected; } /** * Returns the battery level in the range of [0, 1], if present. May return null, if Android * returns a null or malformed Intent. */ public Float getBatteryLevel() { return level; } /** * Converts the battery level and power connectivity to a velocity that mimics the iOS * UIDeviceBatteryState. * * @return an int value that mimics the UIDeviceBatteryState enum. */ public int getBatteryVelocity() { if (!powerConnected || level == null) { return VELOCITY_UNPLUGGED; } else if (level < 0.99) { return VELOCITY_CHARGING; } else { return VELOCITY_FULL; } } /** Creates a new BatteryState using data from the given Context. */ public static BatteryState get(Context context) { boolean powerConnected = false; Float level = null; final IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); final Intent batteryStatusIntent = context.registerReceiver(null, ifilter); if (batteryStatusIntent != null) { powerConnected = isPowerConnected(batteryStatusIntent); level = getLevel(batteryStatusIntent); } return new BatteryState(level, powerConnected); } /** * Returns whether the power is connected, according to the given Intent. * * @param batteryStatusIntent from a call to registerReceiver on ACTION_BATTERY_CHANGED. * @return true if plugged in. */ private static boolean isPowerConnected(Intent batteryStatusIntent) { final int status = batteryStatusIntent.getIntExtra(BatteryManager.EXTRA_STATUS, -1); if (status == -1) { return false; } return status == BatteryManager.BATTERY_STATUS_CHARGING || status == BatteryManager.BATTERY_STATUS_FULL; } /** * Gets the battery level, based on the given Intent. * * @param batteryStatusIntent from a call to registerReceiver on ACTION_BATTERY_CHANGED. * @return battery level in range [0, 1], if data is present, else null. */ private static Float getLevel(Intent batteryStatusIntent) { final int level = batteryStatusIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); final int scale = batteryStatusIntent.getIntExtra(BatteryManager.EXTRA_SCALE, -1); if (level == -1 || scale == -1) { return null; } return level / (float) scale; } }