File indexing completed on 2025-02-02 04:47:49

0001 /*
0002  * SPDX-FileCopyrightText: 2014 Albert Vaca Cintora <albertvaka@gmail.com>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  */
0006 
0007 package org.kde.kdeconnect.Plugins.BatteryPlugin;
0008 
0009 import android.content.BroadcastReceiver;
0010 import android.content.Context;
0011 import android.content.Intent;
0012 import android.content.IntentFilter;
0013 import android.os.BatteryManager;
0014 
0015 import androidx.annotation.NonNull;
0016 import androidx.annotation.Nullable;
0017 
0018 import org.kde.kdeconnect.NetworkPacket;
0019 import org.kde.kdeconnect.Plugins.Plugin;
0020 import org.kde.kdeconnect.Plugins.PluginFactory;
0021 import org.kde.kdeconnect_tp.R;
0022 
0023 @PluginFactory.LoadablePlugin
0024 public class BatteryPlugin extends Plugin {
0025 
0026     private final static String PACKET_TYPE_BATTERY = "kdeconnect.battery";
0027 
0028     // keep these fields in sync with kdeconnect-kded:BatteryPlugin.h:ThresholdBatteryEvent
0029     private static final int THRESHOLD_EVENT_NONE = 0;
0030     private static final int THRESHOLD_EVENT_BATTERY_LOW = 1;
0031 
0032     public static boolean isLowBattery(@NonNull DeviceBatteryInfo info) {
0033         return info.getThresholdEvent() == THRESHOLD_EVENT_BATTERY_LOW;
0034     }
0035 
0036     private final NetworkPacket batteryInfo = new NetworkPacket(PACKET_TYPE_BATTERY);
0037 
0038     @Nullable
0039     private DeviceBatteryInfo remoteBatteryInfo;
0040 
0041     @Override
0042     public @NonNull String getDisplayName() {
0043         return context.getResources().getString(R.string.pref_plugin_battery);
0044     }
0045 
0046     @Override
0047     public @NonNull String getDescription() {
0048         return context.getResources().getString(R.string.pref_plugin_battery_desc);
0049     }
0050 
0051     private final BroadcastReceiver receiver = new BroadcastReceiver() {
0052 
0053         boolean wasLowBattery = false; // will trigger a low battery notification when the device is connected
0054 
0055         @Override
0056         public void onReceive(Context context, Intent batteryIntent) {
0057 
0058             int level = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
0059             int scale = batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, 1);
0060             int plugged = batteryIntent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
0061 
0062             int currentCharge = (level == -1) ? batteryInfo.getInt("currentCharge") : level * 100 / scale;
0063             boolean isCharging = (plugged == -1) ? batteryInfo.getBoolean("isCharging") : (0 != plugged);
0064 
0065             int thresholdEvent = THRESHOLD_EVENT_NONE;
0066             if (Intent.ACTION_BATTERY_OKAY.equals(batteryIntent.getAction())) {
0067                 wasLowBattery = false;
0068             } else if (Intent.ACTION_BATTERY_LOW.equals(batteryIntent.getAction())) {
0069                 if (!wasLowBattery && !isCharging) {
0070                     thresholdEvent = THRESHOLD_EVENT_BATTERY_LOW;
0071                 }
0072                 wasLowBattery = true;
0073             }
0074 
0075             if (isCharging != batteryInfo.getBoolean("isCharging")
0076                     || currentCharge != batteryInfo.getInt("currentCharge")
0077                     || thresholdEvent != batteryInfo.getInt("thresholdEvent")
0078                     ) {
0079 
0080                 batteryInfo.set("currentCharge", currentCharge);
0081                 batteryInfo.set("isCharging", isCharging);
0082                 batteryInfo.set("thresholdEvent", thresholdEvent);
0083                 device.sendPacket(batteryInfo);
0084 
0085             }
0086         }
0087     };
0088 
0089     @Override
0090     public boolean onCreate() {
0091         IntentFilter intentFilter = new IntentFilter();
0092         intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
0093         intentFilter.addAction(Intent.ACTION_BATTERY_LOW);
0094         intentFilter.addAction(Intent.ACTION_BATTERY_OKAY);
0095         Intent currentState = context.registerReceiver(receiver, intentFilter);
0096         receiver.onReceive(context, currentState);
0097         return true;
0098     }
0099 
0100     @Override
0101     public void onDestroy() {
0102         //It's okay to call this only once, even though we registered it for two filters
0103         context.unregisterReceiver(receiver);
0104     }
0105 
0106     @Override
0107     public boolean onPacketReceived(@NonNull NetworkPacket np) {
0108         if (!PACKET_TYPE_BATTERY.equals(np.getType())) {
0109             return false;
0110         }
0111         remoteBatteryInfo = new DeviceBatteryInfo(np);
0112         device.onPluginsChanged();
0113         return true;
0114     }
0115 
0116     /**
0117      * The latest battery information about the linked device. Will be null if the linked device
0118      * has not sent us any such information yet.
0119      * <p>
0120      * See {@link DeviceBatteryInfo} for info on which fields we expect to find.
0121      * </p>
0122      *
0123      * @return the most recent packet received from the remote device. May be null
0124      */
0125     @Nullable
0126     public DeviceBatteryInfo getRemoteBatteryInfo() {
0127         return remoteBatteryInfo;
0128     }
0129 
0130     @Override
0131     public @NonNull String[] getSupportedPacketTypes() {
0132         return new String[]{PACKET_TYPE_BATTERY};
0133     }
0134 
0135     @Override
0136     public @NonNull String[] getOutgoingPacketTypes() {
0137         return new String[]{PACKET_TYPE_BATTERY};
0138     }
0139 
0140 }