Merge "Listen for EXTRA_PRESENT changes" into rvc-qpr-dev
This commit is contained in:
@@ -25,6 +25,7 @@ import static android.os.BatteryManager.EXTRA_LEVEL;
|
|||||||
import static android.os.BatteryManager.EXTRA_MAX_CHARGING_CURRENT;
|
import static android.os.BatteryManager.EXTRA_MAX_CHARGING_CURRENT;
|
||||||
import static android.os.BatteryManager.EXTRA_MAX_CHARGING_VOLTAGE;
|
import static android.os.BatteryManager.EXTRA_MAX_CHARGING_VOLTAGE;
|
||||||
import static android.os.BatteryManager.EXTRA_PLUGGED;
|
import static android.os.BatteryManager.EXTRA_PLUGGED;
|
||||||
|
import static android.os.BatteryManager.EXTRA_PRESENT;
|
||||||
import static android.os.BatteryManager.EXTRA_STATUS;
|
import static android.os.BatteryManager.EXTRA_STATUS;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -50,14 +51,16 @@ public class BatteryStatus {
|
|||||||
public final int plugged;
|
public final int plugged;
|
||||||
public final int health;
|
public final int health;
|
||||||
public final int maxChargingWattage;
|
public final int maxChargingWattage;
|
||||||
|
public final boolean present;
|
||||||
|
|
||||||
public BatteryStatus(int status, int level, int plugged, int health,
|
public BatteryStatus(int status, int level, int plugged, int health,
|
||||||
int maxChargingWattage) {
|
int maxChargingWattage, boolean present) {
|
||||||
this.status = status;
|
this.status = status;
|
||||||
this.level = level;
|
this.level = level;
|
||||||
this.plugged = plugged;
|
this.plugged = plugged;
|
||||||
this.health = health;
|
this.health = health;
|
||||||
this.maxChargingWattage = maxChargingWattage;
|
this.maxChargingWattage = maxChargingWattage;
|
||||||
|
this.present = present;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BatteryStatus(Intent batteryChangedIntent) {
|
public BatteryStatus(Intent batteryChangedIntent) {
|
||||||
@@ -65,6 +68,7 @@ public class BatteryStatus {
|
|||||||
plugged = batteryChangedIntent.getIntExtra(EXTRA_PLUGGED, 0);
|
plugged = batteryChangedIntent.getIntExtra(EXTRA_PLUGGED, 0);
|
||||||
level = batteryChangedIntent.getIntExtra(EXTRA_LEVEL, 0);
|
level = batteryChangedIntent.getIntExtra(EXTRA_LEVEL, 0);
|
||||||
health = batteryChangedIntent.getIntExtra(EXTRA_HEALTH, BATTERY_HEALTH_UNKNOWN);
|
health = batteryChangedIntent.getIntExtra(EXTRA_HEALTH, BATTERY_HEALTH_UNKNOWN);
|
||||||
|
present = batteryChangedIntent.getBooleanExtra(EXTRA_PRESENT, true);
|
||||||
|
|
||||||
final int maxChargingMicroAmp = batteryChangedIntent.getIntExtra(EXTRA_MAX_CHARGING_CURRENT,
|
final int maxChargingMicroAmp = batteryChangedIntent.getIntExtra(EXTRA_MAX_CHARGING_CURRENT,
|
||||||
-1);
|
-1);
|
||||||
|
|||||||
24
packages/SystemUI/res/drawable/ic_battery_unknown.xml
Normal file
24
packages/SystemUI/res/drawable/ic_battery_unknown.xml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<!--
|
||||||
|
Copyright (C) 2020 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.
|
||||||
|
-->
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="12dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="12.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:pathData="M10.404,2.4L8.4,2.4L8.4,0L3.6,0L3.6,2.4L1.596,2.4C0.72,2.4 0,3.12 0,3.996L0,22.392C0,23.28 0.72,24 1.596,24L10.392,24C11.28,24 12,23.28 12,22.404L12,3.996C12,3.12 11.28,2.4 10.404,2.4ZM7.14,19.14L4.86,19.14L4.86,16.86L7.14,16.86L7.14,19.14ZM8.76,12.828C8.76,12.828 8.304,13.332 7.956,13.68C7.38,14.256 6.96,15.06 6.96,15.6L5.04,15.6C5.04,14.604 5.592,13.776 6.156,13.2L7.272,12.072C7.596,11.748 7.8,11.292 7.8,10.8C7.8,9.804 6.996,9 6,9C5.004,9 4.2,9.804 4.2,10.8L2.4,10.8C2.4,8.808 4.008,7.2 6,7.2C7.992,7.2 9.6,8.808 9.6,10.8C9.6,11.592 9.276,12.312 8.76,12.828L8.76,12.828Z"
|
||||||
|
android:fillColor="#ffffff" />
|
||||||
|
</vector>
|
||||||
@@ -579,4 +579,9 @@
|
|||||||
<integer name="controls_max_columns_adjust_below_width_dp">320</integer>
|
<integer name="controls_max_columns_adjust_below_width_dp">320</integer>
|
||||||
<!-- If the config font scale is >= this value, potentially adjust the number of columns-->
|
<!-- If the config font scale is >= this value, potentially adjust the number of columns-->
|
||||||
<item name="controls_max_columns_adjust_above_font_scale" translatable="false" format="float" type="dimen">1.25</item>
|
<item name="controls_max_columns_adjust_above_font_scale" translatable="false" format="float" type="dimen">1.25</item>
|
||||||
|
|
||||||
|
<!-- Whether or not to show a notification for an unknown battery state -->
|
||||||
|
<bool name="config_showNotificationForUnknownBatteryState">false</bool>
|
||||||
|
<!-- content URL in a notification when ACTION_BATTERY_CHANGED.EXTRA_PRESENT field is false -->
|
||||||
|
<string translatable="false" name="config_batteryStateUnknownUrl"></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -437,6 +437,8 @@
|
|||||||
<string name="accessibility_battery_three_bars">Battery three bars.</string>
|
<string name="accessibility_battery_three_bars">Battery three bars.</string>
|
||||||
<!-- Content description of the battery when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
|
<!-- Content description of the battery when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
|
||||||
<string name="accessibility_battery_full">Battery full.</string>
|
<string name="accessibility_battery_full">Battery full.</string>
|
||||||
|
<!-- Content description of the battery when battery state is unknown for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="accessibility_battery_unknown">Battery percentage unknown.</string>
|
||||||
|
|
||||||
<!-- Content description of the phone signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
|
<!-- Content description of the phone signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
|
||||||
<string name="accessibility_no_phone">No phone.</string>
|
<string name="accessibility_no_phone">No phone.</string>
|
||||||
@@ -2870,4 +2872,11 @@
|
|||||||
<string name="media_output_dialog_connect_failed">Couldn\'t connect. Try again.</string>
|
<string name="media_output_dialog_connect_failed">Couldn\'t connect. Try again.</string>
|
||||||
<!-- Title for pairing item [CHAR LIMIT=60] -->
|
<!-- Title for pairing item [CHAR LIMIT=60] -->
|
||||||
<string name="media_output_dialog_pairing_new">Pair new device</string>
|
<string name="media_output_dialog_pairing_new">Pair new device</string>
|
||||||
|
|
||||||
|
<!-- Title to display in a notification when ACTION_BATTERY_CHANGED.EXTRA_PRESENT field is false
|
||||||
|
[CHAR LIMIT=NONE] -->
|
||||||
|
<string name="battery_state_unknown_notification_title">Problem reading your battery meter</string>
|
||||||
|
<!-- Text to display in a notification when ACTION_BATTERY_CHANGED.EXTRA_PRESENT field is false
|
||||||
|
[CHAR LIMIT=NONE] -->
|
||||||
|
<string name="battery_state_unknown_notification_text">Tap for more information</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -1696,7 +1696,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Take a guess at initial SIM state, battery status and PLMN until we get an update
|
// Take a guess at initial SIM state, battery status and PLMN until we get an update
|
||||||
mBatteryStatus = new BatteryStatus(BATTERY_STATUS_UNKNOWN, 100, 0, 0, 0);
|
mBatteryStatus = new BatteryStatus(BATTERY_STATUS_UNKNOWN, 100, 0, 0, 0, true);
|
||||||
|
|
||||||
// Watch for interesting updates
|
// Watch for interesting updates
|
||||||
final IntentFilter filter = new IntentFilter();
|
final IntentFilter filter = new IntentFilter();
|
||||||
@@ -2563,6 +2563,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
final boolean wasPluggedIn = old.isPluggedIn();
|
final boolean wasPluggedIn = old.isPluggedIn();
|
||||||
final boolean stateChangedWhilePluggedIn = wasPluggedIn && nowPluggedIn
|
final boolean stateChangedWhilePluggedIn = wasPluggedIn && nowPluggedIn
|
||||||
&& (old.status != current.status);
|
&& (old.status != current.status);
|
||||||
|
final boolean nowPresent = current.present;
|
||||||
|
final boolean wasPresent = old.present;
|
||||||
|
|
||||||
// change in plug state is always interesting
|
// change in plug state is always interesting
|
||||||
if (wasPluggedIn != nowPluggedIn || stateChangedWhilePluggedIn) {
|
if (wasPluggedIn != nowPluggedIn || stateChangedWhilePluggedIn) {
|
||||||
@@ -2584,6 +2586,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Battery either showed up or disappeared
|
||||||
|
if (wasPresent != nowPresent) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import android.content.res.Resources;
|
|||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
import android.database.ContentObserver;
|
import android.database.ContentObserver;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
@@ -95,12 +96,15 @@ public class BatteryMeterView extends LinearLayout implements
|
|||||||
private int mTextColor;
|
private int mTextColor;
|
||||||
private int mLevel;
|
private int mLevel;
|
||||||
private int mShowPercentMode = MODE_DEFAULT;
|
private int mShowPercentMode = MODE_DEFAULT;
|
||||||
private boolean mForceShowPercent;
|
|
||||||
private boolean mShowPercentAvailable;
|
private boolean mShowPercentAvailable;
|
||||||
// Some places may need to show the battery conditionally, and not obey the tuner
|
// Some places may need to show the battery conditionally, and not obey the tuner
|
||||||
private boolean mIgnoreTunerUpdates;
|
private boolean mIgnoreTunerUpdates;
|
||||||
private boolean mIsSubscribedForTunerUpdates;
|
private boolean mIsSubscribedForTunerUpdates;
|
||||||
private boolean mCharging;
|
private boolean mCharging;
|
||||||
|
// Error state where we know nothing about the current battery state
|
||||||
|
private boolean mBatteryStateUnknown;
|
||||||
|
// Lazily-loaded since this is expected to be a rare-if-ever state
|
||||||
|
private Drawable mUnknownStateDrawable;
|
||||||
|
|
||||||
private DualToneHandler mDualToneHandler;
|
private DualToneHandler mDualToneHandler;
|
||||||
private int mUser;
|
private int mUser;
|
||||||
@@ -350,6 +354,11 @@ public class BatteryMeterView extends LinearLayout implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updatePercentText() {
|
private void updatePercentText() {
|
||||||
|
if (mBatteryStateUnknown) {
|
||||||
|
setContentDescription(getContext().getString(R.string.accessibility_battery_unknown));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (mBatteryController == null) {
|
if (mBatteryController == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -390,9 +399,13 @@ public class BatteryMeterView extends LinearLayout implements
|
|||||||
final boolean systemSetting = 0 != whitelistIpcs(() -> Settings.System
|
final boolean systemSetting = 0 != whitelistIpcs(() -> Settings.System
|
||||||
.getIntForUser(getContext().getContentResolver(),
|
.getIntForUser(getContext().getContentResolver(),
|
||||||
SHOW_BATTERY_PERCENT, 0, mUser));
|
SHOW_BATTERY_PERCENT, 0, mUser));
|
||||||
|
boolean shouldShow =
|
||||||
|
(mShowPercentAvailable && systemSetting && mShowPercentMode != MODE_OFF)
|
||||||
|
|| mShowPercentMode == MODE_ON
|
||||||
|
|| mShowPercentMode == MODE_ESTIMATE;
|
||||||
|
shouldShow = shouldShow && !mBatteryStateUnknown;
|
||||||
|
|
||||||
if ((mShowPercentAvailable && systemSetting && mShowPercentMode != MODE_OFF)
|
if (shouldShow) {
|
||||||
|| mShowPercentMode == MODE_ON || mShowPercentMode == MODE_ESTIMATE) {
|
|
||||||
if (!showing) {
|
if (!showing) {
|
||||||
mBatteryPercentView = loadPercentView();
|
mBatteryPercentView = loadPercentView();
|
||||||
if (mPercentageStyleId != 0) { // Only set if specified as attribute
|
if (mPercentageStyleId != 0) { // Only set if specified as attribute
|
||||||
@@ -418,6 +431,32 @@ public class BatteryMeterView extends LinearLayout implements
|
|||||||
scaleBatteryMeterViews();
|
scaleBatteryMeterViews();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Drawable getUnknownStateDrawable() {
|
||||||
|
if (mUnknownStateDrawable == null) {
|
||||||
|
mUnknownStateDrawable = mContext.getDrawable(R.drawable.ic_battery_unknown);
|
||||||
|
mUnknownStateDrawable.setTint(mTextColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mUnknownStateDrawable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBatteryUnknownStateChanged(boolean isUnknown) {
|
||||||
|
if (mBatteryStateUnknown == isUnknown) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mBatteryStateUnknown = isUnknown;
|
||||||
|
|
||||||
|
if (mBatteryStateUnknown) {
|
||||||
|
mBatteryIconView.setImageDrawable(getUnknownStateDrawable());
|
||||||
|
} else {
|
||||||
|
mBatteryIconView.setImageDrawable(mDrawable);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateShowPercent();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Looks up the scale factor for status bar icons and scales the battery view by that amount.
|
* Looks up the scale factor for status bar icons and scales the battery view by that amount.
|
||||||
*/
|
*/
|
||||||
@@ -458,6 +497,10 @@ public class BatteryMeterView extends LinearLayout implements
|
|||||||
if (mBatteryPercentView != null) {
|
if (mBatteryPercentView != null) {
|
||||||
mBatteryPercentView.setTextColor(singleToneColor);
|
mBatteryPercentView.setTextColor(singleToneColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mUnknownStateDrawable != null) {
|
||||||
|
mUnknownStateDrawable.setTint(singleToneColor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
||||||
@@ -467,8 +510,8 @@ public class BatteryMeterView extends LinearLayout implements
|
|||||||
pw.println(" mDrawable.getPowerSave: " + powerSave);
|
pw.println(" mDrawable.getPowerSave: " + powerSave);
|
||||||
pw.println(" mBatteryPercentView.getText(): " + percent);
|
pw.println(" mBatteryPercentView.getText(): " + percent);
|
||||||
pw.println(" mTextColor: #" + Integer.toHexString(mTextColor));
|
pw.println(" mTextColor: #" + Integer.toHexString(mTextColor));
|
||||||
|
pw.println(" mBatteryStateUnknown: " + mBatteryStateUnknown);
|
||||||
pw.println(" mLevel: " + mLevel);
|
pw.println(" mLevel: " + mLevel);
|
||||||
pw.println(" mForceShowPercent: " + mForceShowPercent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class SettingObserver extends ContentObserver {
|
private final class SettingObserver extends ContentObserver {
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import com.android.systemui.dagger.qualifiers.Main;
|
|||||||
import com.android.systemui.dump.DumpHandler;
|
import com.android.systemui.dump.DumpHandler;
|
||||||
import com.android.systemui.dump.LogBufferFreezer;
|
import com.android.systemui.dump.LogBufferFreezer;
|
||||||
import com.android.systemui.dump.SystemUIAuxiliaryDumpService;
|
import com.android.systemui.dump.SystemUIAuxiliaryDumpService;
|
||||||
|
import com.android.systemui.statusbar.policy.BatteryStateNotifier;
|
||||||
|
|
||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
@@ -44,18 +45,21 @@ public class SystemUIService extends Service {
|
|||||||
private final DumpHandler mDumpHandler;
|
private final DumpHandler mDumpHandler;
|
||||||
private final BroadcastDispatcher mBroadcastDispatcher;
|
private final BroadcastDispatcher mBroadcastDispatcher;
|
||||||
private final LogBufferFreezer mLogBufferFreezer;
|
private final LogBufferFreezer mLogBufferFreezer;
|
||||||
|
private final BatteryStateNotifier mBatteryStateNotifier;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public SystemUIService(
|
public SystemUIService(
|
||||||
@Main Handler mainHandler,
|
@Main Handler mainHandler,
|
||||||
DumpHandler dumpHandler,
|
DumpHandler dumpHandler,
|
||||||
BroadcastDispatcher broadcastDispatcher,
|
BroadcastDispatcher broadcastDispatcher,
|
||||||
LogBufferFreezer logBufferFreezer) {
|
LogBufferFreezer logBufferFreezer,
|
||||||
|
BatteryStateNotifier batteryStateNotifier) {
|
||||||
super();
|
super();
|
||||||
mMainHandler = mainHandler;
|
mMainHandler = mainHandler;
|
||||||
mDumpHandler = dumpHandler;
|
mDumpHandler = dumpHandler;
|
||||||
mBroadcastDispatcher = broadcastDispatcher;
|
mBroadcastDispatcher = broadcastDispatcher;
|
||||||
mLogBufferFreezer = logBufferFreezer;
|
mLogBufferFreezer = logBufferFreezer;
|
||||||
|
mBatteryStateNotifier = batteryStateNotifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -68,6 +72,11 @@ public class SystemUIService extends Service {
|
|||||||
// Finish initializing dump logic
|
// Finish initializing dump logic
|
||||||
mLogBufferFreezer.attach(mBroadcastDispatcher);
|
mLogBufferFreezer.attach(mBroadcastDispatcher);
|
||||||
|
|
||||||
|
// If configured, set up a battery notification
|
||||||
|
if (getResources().getBoolean(R.bool.config_showNotificationForUnknownBatteryState)) {
|
||||||
|
mBatteryStateNotifier.startListening();
|
||||||
|
}
|
||||||
|
|
||||||
// For debugging RescueParty
|
// For debugging RescueParty
|
||||||
if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean("debug.crash_sysui", false)) {
|
if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean("debug.crash_sysui", false)) {
|
||||||
throw new RuntimeException();
|
throw new RuntimeException();
|
||||||
|
|||||||
@@ -123,6 +123,7 @@ public class KeyguardIndicationController implements StateListener,
|
|||||||
private int mChargingSpeed;
|
private int mChargingSpeed;
|
||||||
private int mChargingWattage;
|
private int mChargingWattage;
|
||||||
private int mBatteryLevel;
|
private int mBatteryLevel;
|
||||||
|
private boolean mBatteryPresent = true;
|
||||||
private long mChargingTimeRemaining;
|
private long mChargingTimeRemaining;
|
||||||
private float mDisclosureMaxAlpha;
|
private float mDisclosureMaxAlpha;
|
||||||
private String mMessageToShowOnScreenOn;
|
private String mMessageToShowOnScreenOn;
|
||||||
@@ -391,86 +392,103 @@ public class KeyguardIndicationController implements StateListener,
|
|||||||
mWakeLock.setAcquired(false);
|
mWakeLock.setAcquired(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mVisible) {
|
if (!mVisible) {
|
||||||
// Walk down a precedence-ordered list of what indication
|
return;
|
||||||
// should be shown based on user or device state
|
}
|
||||||
if (mDozing) {
|
|
||||||
// When dozing we ignore any text color and use white instead, because
|
|
||||||
// colors can be hard to read in low brightness.
|
|
||||||
mTextView.setTextColor(Color.WHITE);
|
|
||||||
if (!TextUtils.isEmpty(mTransientIndication)) {
|
|
||||||
mTextView.switchIndication(mTransientIndication);
|
|
||||||
} else if (!TextUtils.isEmpty(mAlignmentIndication)) {
|
|
||||||
mTextView.switchIndication(mAlignmentIndication);
|
|
||||||
mTextView.setTextColor(mContext.getColor(R.color.misalignment_text_color));
|
|
||||||
} else if (mPowerPluggedIn || mEnableBatteryDefender) {
|
|
||||||
String indication = computePowerIndication();
|
|
||||||
if (animate) {
|
|
||||||
animateText(mTextView, indication);
|
|
||||||
} else {
|
|
||||||
mTextView.switchIndication(indication);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
String percentage = NumberFormat.getPercentInstance()
|
|
||||||
.format(mBatteryLevel / 100f);
|
|
||||||
mTextView.switchIndication(percentage);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int userId = KeyguardUpdateMonitor.getCurrentUser();
|
// A few places might need to hide the indication, so always start by making it visible
|
||||||
String trustGrantedIndication = getTrustGrantedIndication();
|
mIndicationArea.setVisibility(View.VISIBLE);
|
||||||
String trustManagedIndication = getTrustManagedIndication();
|
|
||||||
|
|
||||||
String powerIndication = null;
|
// Walk down a precedence-ordered list of what indication
|
||||||
if (mPowerPluggedIn || mEnableBatteryDefender) {
|
// should be shown based on user or device state
|
||||||
powerIndication = computePowerIndication();
|
if (mDozing) {
|
||||||
}
|
// When dozing we ignore any text color and use white instead, because
|
||||||
|
// colors can be hard to read in low brightness.
|
||||||
boolean isError = false;
|
mTextView.setTextColor(Color.WHITE);
|
||||||
if (!mKeyguardUpdateMonitor.isUserUnlocked(userId)) {
|
if (!TextUtils.isEmpty(mTransientIndication)) {
|
||||||
mTextView.switchIndication(com.android.internal.R.string.lockscreen_storage_locked);
|
mTextView.switchIndication(mTransientIndication);
|
||||||
} else if (!TextUtils.isEmpty(mTransientIndication)) {
|
} else if (!mBatteryPresent) {
|
||||||
if (powerIndication != null && !mTransientIndication.equals(powerIndication)) {
|
// If there is no battery detected, hide the indication and bail
|
||||||
String indication = mContext.getResources().getString(
|
mIndicationArea.setVisibility(View.GONE);
|
||||||
R.string.keyguard_indication_trust_unlocked_plugged_in,
|
|
||||||
mTransientIndication, powerIndication);
|
|
||||||
mTextView.switchIndication(indication);
|
|
||||||
} else {
|
|
||||||
mTextView.switchIndication(mTransientIndication);
|
|
||||||
}
|
|
||||||
isError = mTransientTextIsError;
|
|
||||||
} else if (!TextUtils.isEmpty(trustGrantedIndication)
|
|
||||||
&& mKeyguardUpdateMonitor.getUserHasTrust(userId)) {
|
|
||||||
if (powerIndication != null) {
|
|
||||||
String indication = mContext.getResources().getString(
|
|
||||||
R.string.keyguard_indication_trust_unlocked_plugged_in,
|
|
||||||
trustGrantedIndication, powerIndication);
|
|
||||||
mTextView.switchIndication(indication);
|
|
||||||
} else {
|
|
||||||
mTextView.switchIndication(trustGrantedIndication);
|
|
||||||
}
|
|
||||||
} else if (!TextUtils.isEmpty(mAlignmentIndication)) {
|
} else if (!TextUtils.isEmpty(mAlignmentIndication)) {
|
||||||
mTextView.switchIndication(mAlignmentIndication);
|
mTextView.switchIndication(mAlignmentIndication);
|
||||||
isError = true;
|
mTextView.setTextColor(mContext.getColor(R.color.misalignment_text_color));
|
||||||
} else if (mPowerPluggedIn || mEnableBatteryDefender) {
|
} else if (mPowerPluggedIn || mEnableBatteryDefender) {
|
||||||
if (DEBUG_CHARGING_SPEED) {
|
String indication = computePowerIndication();
|
||||||
powerIndication += ", " + (mChargingWattage / 1000) + " mW";
|
|
||||||
}
|
|
||||||
if (animate) {
|
if (animate) {
|
||||||
animateText(mTextView, powerIndication);
|
animateText(mTextView, indication);
|
||||||
} else {
|
} else {
|
||||||
mTextView.switchIndication(powerIndication);
|
mTextView.switchIndication(indication);
|
||||||
}
|
}
|
||||||
} else if (!TextUtils.isEmpty(trustManagedIndication)
|
|
||||||
&& mKeyguardUpdateMonitor.getUserTrustIsManaged(userId)
|
|
||||||
&& !mKeyguardUpdateMonitor.getUserHasTrust(userId)) {
|
|
||||||
mTextView.switchIndication(trustManagedIndication);
|
|
||||||
} else {
|
} else {
|
||||||
mTextView.switchIndication(mRestingIndication);
|
String percentage = NumberFormat.getPercentInstance()
|
||||||
|
.format(mBatteryLevel / 100f);
|
||||||
|
mTextView.switchIndication(percentage);
|
||||||
}
|
}
|
||||||
mTextView.setTextColor(isError ? Utils.getColorError(mContext)
|
return;
|
||||||
: mInitialTextColorState);
|
}
|
||||||
|
|
||||||
|
int userId = KeyguardUpdateMonitor.getCurrentUser();
|
||||||
|
String trustGrantedIndication = getTrustGrantedIndication();
|
||||||
|
String trustManagedIndication = getTrustManagedIndication();
|
||||||
|
|
||||||
|
String powerIndication = null;
|
||||||
|
if (mPowerPluggedIn || mEnableBatteryDefender) {
|
||||||
|
powerIndication = computePowerIndication();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some cases here might need to hide the indication (if the battery is not present)
|
||||||
|
boolean hideIndication = false;
|
||||||
|
boolean isError = false;
|
||||||
|
if (!mKeyguardUpdateMonitor.isUserUnlocked(userId)) {
|
||||||
|
mTextView.switchIndication(com.android.internal.R.string.lockscreen_storage_locked);
|
||||||
|
} else if (!TextUtils.isEmpty(mTransientIndication)) {
|
||||||
|
if (powerIndication != null && !mTransientIndication.equals(powerIndication)) {
|
||||||
|
String indication = mContext.getResources().getString(
|
||||||
|
R.string.keyguard_indication_trust_unlocked_plugged_in,
|
||||||
|
mTransientIndication, powerIndication);
|
||||||
|
mTextView.switchIndication(indication);
|
||||||
|
hideIndication = !mBatteryPresent;
|
||||||
|
} else {
|
||||||
|
mTextView.switchIndication(mTransientIndication);
|
||||||
|
}
|
||||||
|
isError = mTransientTextIsError;
|
||||||
|
} else if (!TextUtils.isEmpty(trustGrantedIndication)
|
||||||
|
&& mKeyguardUpdateMonitor.getUserHasTrust(userId)) {
|
||||||
|
if (powerIndication != null) {
|
||||||
|
String indication = mContext.getResources().getString(
|
||||||
|
R.string.keyguard_indication_trust_unlocked_plugged_in,
|
||||||
|
trustGrantedIndication, powerIndication);
|
||||||
|
mTextView.switchIndication(indication);
|
||||||
|
hideIndication = !mBatteryPresent;
|
||||||
|
} else {
|
||||||
|
mTextView.switchIndication(trustGrantedIndication);
|
||||||
|
}
|
||||||
|
} else if (!TextUtils.isEmpty(mAlignmentIndication)) {
|
||||||
|
mTextView.switchIndication(mAlignmentIndication);
|
||||||
|
isError = true;
|
||||||
|
hideIndication = !mBatteryPresent;
|
||||||
|
} else if (mPowerPluggedIn || mEnableBatteryDefender) {
|
||||||
|
if (DEBUG_CHARGING_SPEED) {
|
||||||
|
powerIndication += ", " + (mChargingWattage / 1000) + " mW";
|
||||||
|
}
|
||||||
|
if (animate) {
|
||||||
|
animateText(mTextView, powerIndication);
|
||||||
|
} else {
|
||||||
|
mTextView.switchIndication(powerIndication);
|
||||||
|
}
|
||||||
|
hideIndication = !mBatteryPresent;
|
||||||
|
} else if (!TextUtils.isEmpty(trustManagedIndication)
|
||||||
|
&& mKeyguardUpdateMonitor.getUserTrustIsManaged(userId)
|
||||||
|
&& !mKeyguardUpdateMonitor.getUserHasTrust(userId)) {
|
||||||
|
mTextView.switchIndication(trustManagedIndication);
|
||||||
|
} else {
|
||||||
|
mTextView.switchIndication(mRestingIndication);
|
||||||
|
}
|
||||||
|
mTextView.setTextColor(isError ? Utils.getColorError(mContext)
|
||||||
|
: mInitialTextColorState);
|
||||||
|
if (hideIndication) {
|
||||||
|
mIndicationArea.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -654,6 +672,7 @@ public class KeyguardIndicationController implements StateListener,
|
|||||||
pw.println(" mMessageToShowOnScreenOn: " + mMessageToShowOnScreenOn);
|
pw.println(" mMessageToShowOnScreenOn: " + mMessageToShowOnScreenOn);
|
||||||
pw.println(" mDozing: " + mDozing);
|
pw.println(" mDozing: " + mDozing);
|
||||||
pw.println(" mBatteryLevel: " + mBatteryLevel);
|
pw.println(" mBatteryLevel: " + mBatteryLevel);
|
||||||
|
pw.println(" mBatteryPresent: " + mBatteryPresent);
|
||||||
pw.println(" mTextView.getText(): " + (mTextView == null ? null : mTextView.getText()));
|
pw.println(" mTextView.getText(): " + (mTextView == null ? null : mTextView.getText()));
|
||||||
pw.println(" computePowerIndication(): " + computePowerIndication());
|
pw.println(" computePowerIndication(): " + computePowerIndication());
|
||||||
}
|
}
|
||||||
@@ -694,6 +713,7 @@ public class KeyguardIndicationController implements StateListener,
|
|||||||
mBatteryLevel = status.level;
|
mBatteryLevel = status.level;
|
||||||
mBatteryOverheated = status.isOverheated();
|
mBatteryOverheated = status.isOverheated();
|
||||||
mEnableBatteryDefender = mBatteryOverheated && status.isPluggedIn();
|
mEnableBatteryDefender = mBatteryOverheated && status.isPluggedIn();
|
||||||
|
mBatteryPresent = status.present;
|
||||||
try {
|
try {
|
||||||
mChargingTimeRemaining = mPowerPluggedIn
|
mChargingTimeRemaining = mPowerPluggedIn
|
||||||
? mBatteryInfo.computeChargeTimeRemaining() : -1;
|
? mBatteryInfo.computeChargeTimeRemaining() : -1;
|
||||||
|
|||||||
@@ -97,6 +97,9 @@ public interface BatteryController extends DemoMode, Dumpable,
|
|||||||
default void onPowerSaveChanged(boolean isPowerSave) {
|
default void onPowerSaveChanged(boolean isPowerSave) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default void onBatteryUnknownStateChanged(boolean isUnknown) {
|
||||||
|
}
|
||||||
|
|
||||||
default void onReverseChanged(boolean isReverse, int level, String name) {
|
default void onReverseChanged(boolean isReverse, int level, String name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package com.android.systemui.statusbar.policy;
|
package com.android.systemui.statusbar.policy;
|
||||||
|
|
||||||
|
import static android.os.BatteryManager.EXTRA_PRESENT;
|
||||||
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -70,6 +72,7 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
|
|||||||
protected int mLevel;
|
protected int mLevel;
|
||||||
protected boolean mPluggedIn;
|
protected boolean mPluggedIn;
|
||||||
protected boolean mCharging;
|
protected boolean mCharging;
|
||||||
|
private boolean mStateUnknown = false;
|
||||||
private boolean mCharged;
|
private boolean mCharged;
|
||||||
protected boolean mPowerSave;
|
protected boolean mPowerSave;
|
||||||
private boolean mAodPowerSave;
|
private boolean mAodPowerSave;
|
||||||
@@ -126,6 +129,7 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
|
|||||||
pw.print(" mCharging="); pw.println(mCharging);
|
pw.print(" mCharging="); pw.println(mCharging);
|
||||||
pw.print(" mCharged="); pw.println(mCharged);
|
pw.print(" mCharged="); pw.println(mCharged);
|
||||||
pw.print(" mPowerSave="); pw.println(mPowerSave);
|
pw.print(" mPowerSave="); pw.println(mPowerSave);
|
||||||
|
pw.print(" mStateUnknown="); pw.println(mStateUnknown);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -139,8 +143,11 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
|
|||||||
mChangeCallbacks.add(cb);
|
mChangeCallbacks.add(cb);
|
||||||
}
|
}
|
||||||
if (!mHasReceivedBattery) return;
|
if (!mHasReceivedBattery) return;
|
||||||
|
|
||||||
|
// Make sure new callbacks get the correct initial state
|
||||||
cb.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
|
cb.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
|
||||||
cb.onPowerSaveChanged(mPowerSave);
|
cb.onPowerSaveChanged(mPowerSave);
|
||||||
|
cb.onBatteryUnknownStateChanged(mStateUnknown);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -168,6 +175,13 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
|
|||||||
mWirelessCharging = mCharging && intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0)
|
mWirelessCharging = mCharging && intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0)
|
||||||
== BatteryManager.BATTERY_PLUGGED_WIRELESS;
|
== BatteryManager.BATTERY_PLUGGED_WIRELESS;
|
||||||
|
|
||||||
|
boolean present = intent.getBooleanExtra(EXTRA_PRESENT, true);
|
||||||
|
boolean unknown = !present;
|
||||||
|
if (unknown != mStateUnknown) {
|
||||||
|
mStateUnknown = unknown;
|
||||||
|
fireBatteryUnknownStateChanged();
|
||||||
|
}
|
||||||
|
|
||||||
fireBatteryLevelChanged();
|
fireBatteryLevelChanged();
|
||||||
} else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)) {
|
} else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)) {
|
||||||
updatePowerSave();
|
updatePowerSave();
|
||||||
@@ -316,6 +330,15 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void fireBatteryUnknownStateChanged() {
|
||||||
|
synchronized (mChangeCallbacks) {
|
||||||
|
final int n = mChangeCallbacks.size();
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
mChangeCallbacks.get(i).onBatteryUnknownStateChanged(mStateUnknown);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void firePowerSaveChanged() {
|
private void firePowerSaveChanged() {
|
||||||
synchronized (mChangeCallbacks) {
|
synchronized (mChangeCallbacks) {
|
||||||
final int N = mChangeCallbacks.size();
|
final int N = mChangeCallbacks.size();
|
||||||
@@ -340,6 +363,7 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
|
|||||||
String level = args.getString("level");
|
String level = args.getString("level");
|
||||||
String plugged = args.getString("plugged");
|
String plugged = args.getString("plugged");
|
||||||
String powerSave = args.getString("powersave");
|
String powerSave = args.getString("powersave");
|
||||||
|
String present = args.getString("present");
|
||||||
if (level != null) {
|
if (level != null) {
|
||||||
mLevel = Math.min(Math.max(Integer.parseInt(level), 0), 100);
|
mLevel = Math.min(Math.max(Integer.parseInt(level), 0), 100);
|
||||||
}
|
}
|
||||||
@@ -350,6 +374,10 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
|
|||||||
mPowerSave = powerSave.equals("true");
|
mPowerSave = powerSave.equals("true");
|
||||||
firePowerSaveChanged();
|
firePowerSaveChanged();
|
||||||
}
|
}
|
||||||
|
if (present != null) {
|
||||||
|
mStateUnknown = !present.equals("true");
|
||||||
|
fireBatteryUnknownStateChanged();
|
||||||
|
}
|
||||||
fireBatteryLevelChanged();
|
fireBatteryLevelChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 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.systemui.statusbar.policy
|
||||||
|
|
||||||
|
import android.app.Notification
|
||||||
|
import android.app.NotificationChannel
|
||||||
|
import android.app.NotificationManager
|
||||||
|
import android.app.PendingIntent
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
|
import com.android.systemui.R
|
||||||
|
import com.android.systemui.util.concurrency.DelayableExecutor
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listens for important battery states and sends non-dismissible system notifications if there is a
|
||||||
|
* problem
|
||||||
|
*/
|
||||||
|
class BatteryStateNotifier @Inject constructor(
|
||||||
|
val controller: BatteryController,
|
||||||
|
val noMan: NotificationManager,
|
||||||
|
val delayableExecutor: DelayableExecutor,
|
||||||
|
val context: Context
|
||||||
|
) : BatteryController.BatteryStateChangeCallback {
|
||||||
|
var stateUnknown = false
|
||||||
|
|
||||||
|
fun startListening() {
|
||||||
|
controller.addCallback(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stopListening() {
|
||||||
|
controller.removeCallback(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBatteryUnknownStateChanged(isUnknown: Boolean) {
|
||||||
|
stateUnknown = isUnknown
|
||||||
|
if (stateUnknown) {
|
||||||
|
val channel = NotificationChannel("battery_status", "Battery status",
|
||||||
|
NotificationManager.IMPORTANCE_DEFAULT)
|
||||||
|
noMan.createNotificationChannel(channel)
|
||||||
|
|
||||||
|
val intent = Intent(Intent.ACTION_VIEW,
|
||||||
|
Uri.parse(context.getString(R.string.config_batteryStateUnknownUrl)))
|
||||||
|
val pi = PendingIntent.getActivity(context, 0, intent, 0)
|
||||||
|
|
||||||
|
val builder = Notification.Builder(context, channel.id)
|
||||||
|
.setAutoCancel(false)
|
||||||
|
.setContentTitle(
|
||||||
|
context.getString(R.string.battery_state_unknown_notification_title))
|
||||||
|
.setContentText(
|
||||||
|
context.getString(R.string.battery_state_unknown_notification_text))
|
||||||
|
.setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
|
||||||
|
.setContentIntent(pi)
|
||||||
|
.setAutoCancel(true)
|
||||||
|
.setOngoing(true)
|
||||||
|
|
||||||
|
noMan.notify(TAG, ID, builder.build())
|
||||||
|
} else {
|
||||||
|
scheduleNotificationCancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun scheduleNotificationCancel() {
|
||||||
|
val r = {
|
||||||
|
if (!stateUnknown) {
|
||||||
|
noMan.cancel(ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delayableExecutor.executeDelayed(r, DELAY_MILLIS)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private const val TAG = "BatteryStateNotifier"
|
||||||
|
private const val ID = 666
|
||||||
|
private const val DELAY_MILLIS: Long = 4 * 60 * 60 * 1000
|
||||||
@@ -495,7 +495,7 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
|
|||||||
createController();
|
createController();
|
||||||
BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_CHARGING,
|
BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_CHARGING,
|
||||||
80 /* level */, BatteryManager.BATTERY_PLUGGED_WIRELESS, 100 /* health */,
|
80 /* level */, BatteryManager.BATTERY_PLUGGED_WIRELESS, 100 /* health */,
|
||||||
0 /* maxChargingWattage */);
|
0 /* maxChargingWattage */, true /* present */);
|
||||||
|
|
||||||
mController.getKeyguardCallback().onRefreshBatteryInfo(status);
|
mController.getKeyguardCallback().onRefreshBatteryInfo(status);
|
||||||
verify(mIBatteryStats).computeChargeTimeRemaining();
|
verify(mIBatteryStats).computeChargeTimeRemaining();
|
||||||
@@ -507,7 +507,7 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
|
|||||||
createController();
|
createController();
|
||||||
BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_CHARGING,
|
BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_CHARGING,
|
||||||
80 /* level */, 0 /* plugged */, 100 /* health */,
|
80 /* level */, 0 /* plugged */, 100 /* health */,
|
||||||
0 /* maxChargingWattage */);
|
0 /* maxChargingWattage */, true /* present */);
|
||||||
|
|
||||||
mController.getKeyguardCallback().onRefreshBatteryInfo(status);
|
mController.getKeyguardCallback().onRefreshBatteryInfo(status);
|
||||||
verify(mIBatteryStats, never()).computeChargeTimeRemaining();
|
verify(mIBatteryStats, never()).computeChargeTimeRemaining();
|
||||||
@@ -553,7 +553,8 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
|
|||||||
createController();
|
createController();
|
||||||
BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_CHARGING,
|
BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_CHARGING,
|
||||||
80 /* level */, BatteryManager.BATTERY_PLUGGED_AC,
|
80 /* level */, BatteryManager.BATTERY_PLUGGED_AC,
|
||||||
BatteryManager.BATTERY_HEALTH_OVERHEAT, 0 /* maxChargingWattage */);
|
BatteryManager.BATTERY_HEALTH_OVERHEAT, 0 /* maxChargingWattage */,
|
||||||
|
true /* present */);
|
||||||
|
|
||||||
mController.getKeyguardCallback().onRefreshBatteryInfo(status);
|
mController.getKeyguardCallback().onRefreshBatteryInfo(status);
|
||||||
mController.setVisible(true);
|
mController.setVisible(true);
|
||||||
@@ -569,7 +570,8 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
|
|||||||
createController();
|
createController();
|
||||||
BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_DISCHARGING,
|
BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_DISCHARGING,
|
||||||
80 /* level */, BatteryManager.BATTERY_PLUGGED_AC,
|
80 /* level */, BatteryManager.BATTERY_PLUGGED_AC,
|
||||||
BatteryManager.BATTERY_HEALTH_OVERHEAT, 0 /* maxChargingWattage */);
|
BatteryManager.BATTERY_HEALTH_OVERHEAT, 0 /* maxChargingWattage */,
|
||||||
|
true /* present */);
|
||||||
|
|
||||||
mController.getKeyguardCallback().onRefreshBatteryInfo(status);
|
mController.getKeyguardCallback().onRefreshBatteryInfo(status);
|
||||||
mController.setVisible(true);
|
mController.setVisible(true);
|
||||||
@@ -585,7 +587,8 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
|
|||||||
createController();
|
createController();
|
||||||
BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_CHARGING,
|
BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_CHARGING,
|
||||||
100 /* level */, BatteryManager.BATTERY_PLUGGED_AC,
|
100 /* level */, BatteryManager.BATTERY_PLUGGED_AC,
|
||||||
BatteryManager.BATTERY_HEALTH_OVERHEAT, 0 /* maxChargingWattage */);
|
BatteryManager.BATTERY_HEALTH_OVERHEAT, 0 /* maxChargingWattage */,
|
||||||
|
true /* present */);
|
||||||
|
|
||||||
mController.getKeyguardCallback().onRefreshBatteryInfo(status);
|
mController.getKeyguardCallback().onRefreshBatteryInfo(status);
|
||||||
mController.setVisible(true);
|
mController.setVisible(true);
|
||||||
@@ -599,7 +602,7 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
|
|||||||
createController();
|
createController();
|
||||||
BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_DISCHARGING,
|
BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_DISCHARGING,
|
||||||
90 /* level */, 0 /* plugged */, BatteryManager.BATTERY_HEALTH_OVERHEAT,
|
90 /* level */, 0 /* plugged */, BatteryManager.BATTERY_HEALTH_OVERHEAT,
|
||||||
0 /* maxChargingWattage */);
|
0 /* maxChargingWattage */, true /* present */);
|
||||||
|
|
||||||
mController.getKeyguardCallback().onRefreshBatteryInfo(status);
|
mController.getKeyguardCallback().onRefreshBatteryInfo(status);
|
||||||
mController.setDozing(true);
|
mController.setDozing(true);
|
||||||
|
|||||||
@@ -16,7 +16,11 @@
|
|||||||
|
|
||||||
package com.android.systemui.statusbar.policy;
|
package com.android.systemui.statusbar.policy;
|
||||||
|
|
||||||
|
import static android.os.BatteryManager.EXTRA_PRESENT;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.atLeastOnce;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -30,6 +34,7 @@ import android.testing.TestableLooper;
|
|||||||
import com.android.systemui.SysuiTestCase;
|
import com.android.systemui.SysuiTestCase;
|
||||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||||
import com.android.systemui.power.EnhancedEstimates;
|
import com.android.systemui.power.EnhancedEstimates;
|
||||||
|
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@@ -93,4 +98,36 @@ public class BatteryControllerTest extends SysuiTestCase {
|
|||||||
Assert.assertFalse(mBatteryController.isAodPowerSave());
|
Assert.assertFalse(mBatteryController.isAodPowerSave());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBatteryPresentState_notPresent() {
|
||||||
|
// GIVEN a battery state callback listening for changes
|
||||||
|
BatteryStateChangeCallback cb = mock(BatteryStateChangeCallback.class);
|
||||||
|
mBatteryController.addCallback(cb);
|
||||||
|
|
||||||
|
// WHEN the state of the battery becomes unknown
|
||||||
|
Intent i = new Intent(Intent.ACTION_BATTERY_CHANGED);
|
||||||
|
i.putExtra(EXTRA_PRESENT, false);
|
||||||
|
mBatteryController.onReceive(getContext(), i);
|
||||||
|
|
||||||
|
// THEN the callback is notified
|
||||||
|
verify(cb, atLeastOnce()).onBatteryUnknownStateChanged(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBatteryPresentState_callbackAddedAfterStateChange() {
|
||||||
|
// GIVEN a battery state callback
|
||||||
|
BatteryController.BatteryStateChangeCallback cb =
|
||||||
|
mock(BatteryController.BatteryStateChangeCallback.class);
|
||||||
|
|
||||||
|
// GIVEN the state has changed before adding a new callback
|
||||||
|
Intent i = new Intent(Intent.ACTION_BATTERY_CHANGED);
|
||||||
|
i.putExtra(EXTRA_PRESENT, false);
|
||||||
|
mBatteryController.onReceive(getContext(), i);
|
||||||
|
|
||||||
|
// WHEN a callback is added
|
||||||
|
mBatteryController.addCallback(cb);
|
||||||
|
|
||||||
|
// THEN it is informed about the battery state
|
||||||
|
verify(cb, atLeastOnce()).onBatteryUnknownStateChanged(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 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.systemui.statusbar.policy
|
||||||
|
|
||||||
|
import android.app.NotificationManager
|
||||||
|
import android.testing.AndroidTestingRunner
|
||||||
|
import android.testing.TestableLooper.RunWithLooper
|
||||||
|
|
||||||
|
import androidx.test.filters.SmallTest
|
||||||
|
|
||||||
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.util.concurrency.FakeExecutor
|
||||||
|
import com.android.systemui.util.time.FakeSystemClock
|
||||||
|
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mockito.ArgumentMatchers.anyInt
|
||||||
|
import org.mockito.ArgumentMatchers.anyString
|
||||||
|
import org.mockito.Mock
|
||||||
|
import org.mockito.Mockito
|
||||||
|
import org.mockito.Mockito.verify
|
||||||
|
import org.mockito.MockitoAnnotations
|
||||||
|
|
||||||
|
private fun <T> anyObject(): T {
|
||||||
|
return Mockito.anyObject<T>()
|
||||||
|
}
|
||||||
|
|
||||||
|
@RunWith(AndroidTestingRunner::class)
|
||||||
|
@RunWithLooper()
|
||||||
|
@SmallTest
|
||||||
|
class BatteryStateNotifierTest : SysuiTestCase() {
|
||||||
|
@Mock private lateinit var batteryController: BatteryController
|
||||||
|
@Mock private lateinit var noMan: NotificationManager
|
||||||
|
|
||||||
|
private val clock = FakeSystemClock()
|
||||||
|
private val executor = FakeExecutor(clock)
|
||||||
|
|
||||||
|
private lateinit var notifier: BatteryStateNotifier
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
MockitoAnnotations.initMocks(this)
|
||||||
|
notifier = BatteryStateNotifier(batteryController, noMan, executor, context)
|
||||||
|
notifier.startListening()
|
||||||
|
|
||||||
|
context.ensureTestableResources()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testNotifyWhenStateUnknown() {
|
||||||
|
notifier.onBatteryUnknownStateChanged(true)
|
||||||
|
verify(noMan).notify(anyString(), anyInt(), anyObject())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testCancelAfterDelay() {
|
||||||
|
notifier.onBatteryUnknownStateChanged(true)
|
||||||
|
notifier.onBatteryUnknownStateChanged(false)
|
||||||
|
|
||||||
|
clock.advanceTime(DELAY_MILLIS + 1)
|
||||||
|
verify(noMan).cancel(anyInt())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// From BatteryStateNotifier.kt
|
||||||
|
private const val DELAY_MILLIS: Long = 40 * 60 * 60 * 1000
|
||||||
Reference in New Issue
Block a user