1/* 2 * Copyright (C) 2017 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 */ 16package androidx.work.impl.constraints.trackers; 17 18import android.content.Context; 19import android.content.Intent; 20import android.content.IntentFilter; 21import android.os.BatteryManager; 22import android.support.annotation.NonNull; 23import android.support.annotation.RestrictTo; 24import android.util.Log; 25 26/** 27 * Tracks whether or not the device's battery level is low. 28 * @hide 29 */ 30@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 31public class BatteryNotLowTracker extends BroadcastReceiverConstraintTracker<Boolean> { 32 33 private static final String TAG = "BatteryNotLowTracker"; 34 35 /** 36 * {@see https://android.googlesource.com/platform/frameworks/base/+/oreo-release/services/core/java/com/android/server/BatteryService.java#111} 37 */ 38 static final int BATTERY_PLUGGED_NONE = 0; 39 40 /** 41 * {@see https://android.googlesource.com/platform/frameworks/base/+/oreo-release/core/res/res/values/config.xml#986} 42 */ 43 static final float BATTERY_LOW_PERCENTAGE = 0.15f; 44 45 /** 46 * Create an instance of {@link BatteryNotLowTracker}. 47 * @param context The application {@link Context} 48 */ 49 public BatteryNotLowTracker(Context context) { 50 super(context); 51 } 52 53 /** 54 * Based on BatteryService#shouldSendBatteryLowLocked(), but this ignores the previous plugged 55 * state - cannot guarantee the last plugged state because this isn't always tracking. 56 * 57 * {@see https://android.googlesource.com/platform/frameworks/base/+/oreo-release/services/core/java/com/android/server/BatteryService.java#268} 58 */ 59 @Override 60 public Boolean getInitialState() { 61 IntentFilter intentFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); 62 Intent intent = mAppContext.registerReceiver(null, intentFilter); 63 if (intent == null) { 64 Log.e(TAG, "getInitialState - null intent received"); 65 return null; 66 } 67 int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, BATTERY_PLUGGED_NONE); 68 int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1); 69 int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); 70 int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1); 71 float batteryPercentage = level / (float) scale; 72 73 return (plugged != BATTERY_PLUGGED_NONE 74 || status == BatteryManager.BATTERY_STATUS_UNKNOWN 75 || batteryPercentage > BATTERY_LOW_PERCENTAGE); 76 } 77 78 @Override 79 public IntentFilter getIntentFilter() { 80 IntentFilter intentFilter = new IntentFilter(); 81 intentFilter.addAction(Intent.ACTION_BATTERY_OKAY); 82 intentFilter.addAction(Intent.ACTION_BATTERY_LOW); 83 return intentFilter; 84 } 85 86 @Override 87 public void onBroadcastReceive(Context context, @NonNull Intent intent) { 88 if (intent.getAction() == null) { 89 return; 90 } 91 92 Log.d(TAG, String.format("Received %s", intent.getAction())); 93 94 switch (intent.getAction()) { 95 case Intent.ACTION_BATTERY_OKAY: 96 setState(true); 97 break; 98 99 case Intent.ACTION_BATTERY_LOW: 100 setState(false); 101 break; 102 } 103 } 104} 105