| /* |
| * Copyright (C) 2017 The Android Open Source Project |
| * |
| * 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.android.settings.fuelgauge; |
| |
| import android.content.BroadcastReceiver; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.IntentFilter; |
| import android.hardware.usb.UsbManager; |
| import android.os.BatteryManager; |
| import android.os.PowerManager; |
| import android.util.Log; |
| |
| import androidx.annotation.IntDef; |
| import androidx.annotation.VisibleForTesting; |
| |
| import com.android.settings.Utils; |
| |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| |
| /** |
| * Use this broadcastReceiver to listen to the battery change and it will invoke |
| * {@link OnBatteryChangedListener} |
| */ |
| public class BatteryBroadcastReceiver extends BroadcastReceiver { |
| |
| private static final String TAG = "BatteryBroadcastRcvr"; |
| /** |
| * Callback if any of the monitored fields has been changed: |
| * |
| * Battery level(e.g. 100%->99%) |
| * Battery status(e.g. plugged->unplugged) |
| * Battery saver(e.g. off->on) |
| * Battery health(e.g. good->overheat) |
| * Battery charging status(e.g. default->long life) |
| */ |
| public interface OnBatteryChangedListener { |
| void onBatteryChanged(@BatteryUpdateType int type); |
| } |
| |
| @Retention(RetentionPolicy.SOURCE) |
| @IntDef({BatteryUpdateType.MANUAL, |
| BatteryUpdateType.BATTERY_LEVEL, |
| BatteryUpdateType.BATTERY_SAVER, |
| BatteryUpdateType.BATTERY_STATUS, |
| BatteryUpdateType.BATTERY_HEALTH, |
| BatteryUpdateType.CHARGING_STATUS, |
| BatteryUpdateType.BATTERY_NOT_PRESENT}) |
| public @interface BatteryUpdateType { |
| int MANUAL = 0; |
| int BATTERY_LEVEL = 1; |
| int BATTERY_SAVER = 2; |
| int BATTERY_STATUS = 3; |
| int BATTERY_HEALTH = 4; |
| int CHARGING_STATUS = 5; |
| int BATTERY_NOT_PRESENT = 6; |
| } |
| |
| @VisibleForTesting |
| String mBatteryLevel; |
| @VisibleForTesting |
| String mBatteryStatus; |
| @VisibleForTesting |
| int mChargingStatus; |
| @VisibleForTesting |
| int mBatteryHealth; |
| private OnBatteryChangedListener mBatteryListener; |
| private Context mContext; |
| |
| public BatteryBroadcastReceiver(Context context) { |
| mContext = context; |
| } |
| |
| @Override |
| public void onReceive(Context context, Intent intent) { |
| updateBatteryStatus(intent, false /* forceUpdate */); |
| } |
| |
| public void setBatteryChangedListener(OnBatteryChangedListener lsn) { |
| mBatteryListener = lsn; |
| } |
| |
| public void register() { |
| final IntentFilter intentFilter = new IntentFilter(); |
| intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); |
| intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED); |
| intentFilter.addAction(BatteryUtils.BYPASS_DOCK_DEFENDER_ACTION); |
| intentFilter.addAction(UsbManager.ACTION_USB_PORT_COMPLIANCE_CHANGED); |
| |
| final Intent intent = mContext.registerReceiver(this, intentFilter, |
| Context.RECEIVER_EXPORTED); |
| updateBatteryStatus(intent, true /* forceUpdate */); |
| } |
| |
| public void unRegister() { |
| mContext.unregisterReceiver(this); |
| } |
| |
| private void updateBatteryStatus(Intent intent, boolean forceUpdate) { |
| if (intent == null || mBatteryListener == null) { |
| return; |
| } |
| final String action = intent.getAction(); |
| Log.d(TAG, "updateBatteryStatus: action=" + action); |
| if (Intent.ACTION_BATTERY_CHANGED.equals(action)) { |
| final String batteryLevel = Utils.getBatteryPercentage(intent); |
| final String batteryStatus = |
| Utils.getBatteryStatus(mContext, intent, /* compactStatus= */ false); |
| final int chargingStatus = intent.getIntExtra( |
| BatteryManager.EXTRA_CHARGING_STATUS, BatteryManager.CHARGING_POLICY_DEFAULT); |
| final int batteryHealth = intent.getIntExtra( |
| BatteryManager.EXTRA_HEALTH, BatteryManager.BATTERY_HEALTH_UNKNOWN); |
| Log.d( |
| TAG, |
| "Battery changed: level: " |
| + batteryLevel |
| + "| status: " |
| + batteryStatus |
| + "| chargingStatus: " |
| + chargingStatus |
| + "| health: " |
| + batteryHealth); |
| if (!Utils.isBatteryPresent(intent)) { |
| Log.w(TAG, "Problem reading the battery meter."); |
| mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_NOT_PRESENT); |
| } else if (forceUpdate) { |
| mBatteryListener.onBatteryChanged(BatteryUpdateType.MANUAL); |
| } else if (chargingStatus != mChargingStatus) { |
| mBatteryListener.onBatteryChanged(BatteryUpdateType.CHARGING_STATUS); |
| } else if (batteryHealth != mBatteryHealth) { |
| mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_HEALTH); |
| } else if(!batteryLevel.equals(mBatteryLevel)) { |
| mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_LEVEL); |
| } else if (!batteryStatus.equals(mBatteryStatus)) { |
| mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_STATUS); |
| } |
| mBatteryLevel = batteryLevel; |
| mBatteryStatus = batteryStatus; |
| mChargingStatus = chargingStatus; |
| mBatteryHealth = batteryHealth; |
| } else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action)) { |
| mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_SAVER); |
| } else if (BatteryUtils.BYPASS_DOCK_DEFENDER_ACTION.equals(action) |
| || UsbManager.ACTION_USB_PORT_COMPLIANCE_CHANGED.equals(action)) { |
| mBatteryListener.onBatteryChanged(BatteryUpdateType.BATTERY_STATUS); |
| } |
| } |
| } |