Add incompatible charging state on the lockscreen
PRD: https://docs.google.com/document/d/1QyKNpKz45mmYt0_pln4jpVgmbrvxxKPT03BKAJrbrNs/
Test: atest KeyguardIndicationControllerTest KeyguardUpdateMonitorTest
Bug: 246960554
Change-Id: Icde56177a0e38a540ed4825e91e50df3c0bdaa3f
diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml
index f4cef84..51f507c 100644
--- a/packages/SystemUI/res-keyguard/values/strings.xml
+++ b/packages/SystemUI/res-keyguard/values/strings.xml
@@ -55,6 +55,9 @@
<!-- When the lock screen is showing and the phone plugged in, and the defend mode is triggered, say that charging is temporarily limited. -->
<string name="keyguard_plugged_in_charging_limited"><xliff:g id="percentage">%s</xliff:g> • Charging optimized to protect battery</string>
+ <!-- When the lock screen is showing and the phone plugged in with incompatible charger. -->
+ <string name="keyguard_plugged_in_incompatible_charger"><xliff:g id="percentage">%s</xliff:g> • Incompatible charging</string>
+
<!-- On the keyguard screen, when pattern lock is disabled, only tell them to press menu to unlock. This is shown in small font at the bottom. -->
<string name="keyguard_instructions_when_pattern_disabled">Press Menu to unlock.</string>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 9f1c382..5b628f8 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -102,6 +102,7 @@
import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
+import android.hardware.usb.UsbManager;
import android.nfc.NfcAdapter;
import android.os.CancellationSignal;
import android.os.Handler;
@@ -138,6 +139,7 @@
import com.android.keyguard.logging.KeyguardUpdateMonitorLogger;
import com.android.settingslib.WirelessUtils;
import com.android.settingslib.fuelgauge.BatteryStatus;
+import com.android.settingslib.Utils;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.biometrics.AuthController;
@@ -329,6 +331,8 @@
// Battery status
@VisibleForTesting
BatteryStatus mBatteryStatus;
+ @VisibleForTesting
+ boolean mIncompatibleCharger;
private StrongAuthTracker mStrongAuthTracker;
@@ -1572,10 +1576,20 @@
MSG_TIMEZONE_UPDATE, intent.getStringExtra(Intent.EXTRA_TIMEZONE));
mHandler.sendMessage(msg);
} else if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
-
+ // Clear incompatible charger state when device is unplugged.
+ if (!BatteryStatus.isPluggedIn(intent)) {
+ mIncompatibleCharger = false;
+ }
final Message msg = mHandler.obtainMessage(
- MSG_BATTERY_UPDATE, new BatteryStatus(intent));
+ MSG_BATTERY_UPDATE, new BatteryStatus(intent, mIncompatibleCharger));
mHandler.sendMessage(msg);
+ } else if (UsbManager.ACTION_USB_PORT_COMPLIANCE_CHANGED.equals(action)) {
+ mIncompatibleCharger = Utils.containsIncompatibleChargers(context, TAG);
+ BatteryStatus batteryStatus = BatteryStatus.create(context, mIncompatibleCharger);
+ if (batteryStatus != null) {
+ mHandler.sendMessage(
+ mHandler.obtainMessage(MSG_BATTERY_UPDATE, batteryStatus));
+ }
} else if (Intent.ACTION_SIM_STATE_CHANGED.equals(action)) {
SimData args = SimData.fromIntent(intent);
// ACTION_SIM_STATE_CHANGED is rebroadcast after unlocking the device to
@@ -2251,6 +2265,7 @@
filter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
+ filter.addAction(UsbManager.ACTION_USB_PORT_COMPLIANCE_CHANGED);
mBroadcastDispatcher.registerReceiverWithHandler(mBroadcastReceiver, filter, mHandler);
// Since ACTION_SERVICE_STATE is being moved to a non-sticky broadcast, trigger the
// listener now with the service state from the default sub.
@@ -3527,8 +3542,6 @@
final boolean wasPluggedIn = old.isPluggedIn();
final boolean stateChangedWhilePluggedIn = wasPluggedIn && nowPluggedIn
&& (old.status != current.status);
- final boolean nowPresent = current.present;
- final boolean wasPresent = old.present;
// change in plug state is always interesting
if (wasPluggedIn != nowPluggedIn || stateChangedWhilePluggedIn) {
@@ -3545,8 +3558,13 @@
return true;
}
- // Battery either showed up or disappeared
- if (wasPresent != nowPresent) {
+ // change in battery is present or not
+ if (old.present != current.present) {
+ return true;
+ }
+
+ // change in the incompatible charger
+ if (!old.incompatibleCharger.equals(current.incompatibleCharger)) {
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 250900e..d3927a2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -185,6 +185,7 @@
private boolean mPowerCharged;
private boolean mBatteryOverheated;
private boolean mEnableBatteryDefender;
+ private boolean mIncompatibleCharger;
private int mChargingSpeed;
private int mChargingWattage;
private int mBatteryLevel;
@@ -903,6 +904,10 @@
chargingId = R.string.keyguard_plugged_in_charging_limited;
String percentage = NumberFormat.getPercentInstance().format(mBatteryLevel / 100f);
return mContext.getResources().getString(chargingId, percentage);
+ } else if (mPowerPluggedIn && mIncompatibleCharger) {
+ chargingId = R.string.keyguard_plugged_in_incompatible_charger;
+ String percentage = NumberFormat.getPercentInstance().format(mBatteryLevel / 100f);
+ return mContext.getResources().getString(chargingId, percentage);
} else if (mPowerCharged) {
return mContext.getResources().getString(R.string.keyguard_charged);
}
@@ -1063,6 +1068,7 @@
mBatteryPresent = status.present;
mBatteryOverheated = status.isOverheated();
mEnableBatteryDefender = mBatteryOverheated && status.isPluggedIn();
+ mIncompatibleCharger = status.incompatibleCharger.orElse(false);
try {
mChargingTimeRemaining = mPowerPluggedIn
? mBatteryInfo.computeChargeTimeRemaining() : -1;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 4110b5a..841ec4b 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -85,8 +85,12 @@
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorProperties;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
+import android.hardware.usb.UsbManager;
+import android.hardware.usb.UsbPort;
+import android.hardware.usb.UsbPortStatus;
import android.net.Uri;
import android.nfc.NfcAdapter;
+import android.os.BatteryManager;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.Handler;
@@ -117,6 +121,7 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor.BiometricAuthenticated;
import com.android.keyguard.logging.KeyguardUpdateMonitorLogger;
+import com.android.settingslib.fuelgauge.BatteryStatus;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.biometrics.FingerprintInteractiveToAuthProvider;
@@ -238,9 +243,16 @@
private UiEventLogger mUiEventLogger;
@Mock
private GlobalSettings mGlobalSettings;
- private FaceWakeUpTriggersConfig mFaceWakeUpTriggersConfig;
@Mock
private FingerprintInteractiveToAuthProvider mInteractiveToAuthProvider;
+ @Mock
+ private UsbPort mUsbPort;
+ @Mock
+ private UsbManager mUsbManager;
+ @Mock
+ private UsbPortStatus mUsbPortStatus;
+ @Mock
+ private Uri mURI;
private List<FingerprintSensorPropertiesInternal> mFingerprintSensorProperties;
private final int mCurrentUserId = 100;
@@ -252,9 +264,6 @@
@Captor
private ArgumentCaptor<FaceManager.AuthenticationCallback> mAuthenticationCallbackCaptor;
- @Mock
- private Uri mURI;
-
// Direct executor
private final Executor mBackgroundExecutor = Runnable::run;
private final Executor mMainExecutor = Runnable::run;
@@ -264,6 +273,7 @@
private MockitoSession mMockitoSession;
private StatusBarStateController.StateListener mStatusBarStateListener;
private IBiometricEnabledOnKeyguardCallback mBiometricEnabledOnKeyguardCallback;
+ private FaceWakeUpTriggersConfig mFaceWakeUpTriggersConfig;
private final InstanceId mKeyguardInstanceId = InstanceId.fakeInstanceId(999);
@Before
@@ -2373,6 +2383,55 @@
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
}
+ @Test
+ public void testBatteryChangedIntent_refreshBatteryInfo() {
+ mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(mContext, getBatteryIntent());
+
+ BatteryStatus status = verifyRefreshBatteryInfo();
+ assertThat(status.incompatibleCharger.get()).isFalse();
+ assertThat(mKeyguardUpdateMonitor.mIncompatibleCharger).isFalse();
+ }
+
+ @Test
+ public void testUsbComplianceIntent_refreshBatteryInfo() {
+ Context contextSpy = getSpyContext();
+ when(contextSpy.registerReceiver(eq(null), any(IntentFilter.class)))
+ .thenReturn(getBatteryIntent());
+
+ mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(
+ contextSpy, new Intent(UsbManager.ACTION_USB_PORT_COMPLIANCE_CHANGED));
+
+ mTestableLooper.processAllMessages();
+ assertThat(mKeyguardUpdateMonitor.mIncompatibleCharger).isFalse();
+ }
+
+ @Test
+ public void testUsbComplianceIntent_refreshBatteryInfoWithIncompatibleCharger() {
+ Context contextSpy = getSpyContext();
+ setupIncompatibleCharging();
+ when(contextSpy.registerReceiver(eq(null), any(IntentFilter.class)))
+ .thenReturn(getBatteryIntent());
+
+ mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(
+ contextSpy, new Intent(UsbManager.ACTION_USB_PORT_COMPLIANCE_CHANGED));
+
+ mTestableLooper.processAllMessages();
+ assertThat(mKeyguardUpdateMonitor.mIncompatibleCharger).isTrue();
+ }
+
+ @Test
+ public void testBatteryChangedIntent_unplugDevice_resetIncompatibleCharger() {
+ mKeyguardUpdateMonitor.mIncompatibleCharger = true;
+ Intent batteryChangedIntent =
+ getBatteryIntent().putExtra(BatteryManager.EXTRA_PLUGGED, -1);
+
+ mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(mContext, batteryChangedIntent);
+
+ BatteryStatus status = verifyRefreshBatteryInfo();
+ assertThat(status.incompatibleCharger.get()).isFalse();
+ assertThat(mKeyguardUpdateMonitor.mIncompatibleCharger).isFalse();
+ }
+
private void userDeviceLockDown() {
when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
when(mStrongAuthTracker.getStrongAuthForUser(mCurrentUserId))
@@ -2592,6 +2651,37 @@
return intent;
}
+ private BatteryStatus verifyRefreshBatteryInfo() {
+ mTestableLooper.processAllMessages();
+ ArgumentCaptor<BatteryStatus> captor = ArgumentCaptor.forClass(BatteryStatus.class);
+ verify(mTestCallback, atLeastOnce()).onRefreshBatteryInfo(captor.capture());
+ List<BatteryStatus> batteryStatusList = captor.getAllValues();
+ return batteryStatusList.get(batteryStatusList.size() - 1);
+ }
+
+ private void setupIncompatibleCharging() {
+ final List<UsbPort> usbPorts = new ArrayList<>();
+ usbPorts.add(mUsbPort);
+ when(mUsbManager.getPorts()).thenReturn(usbPorts);
+ when(mUsbPort.getStatus()).thenReturn(mUsbPortStatus);
+ when(mUsbPort.supportsComplianceWarnings()).thenReturn(true);
+ when(mUsbPortStatus.isConnected()).thenReturn(true);
+ when(mUsbPortStatus.getComplianceWarnings()).thenReturn(new int[]{1});
+ }
+
+ private Context getSpyContext() {
+ Context contextSpy = spy(mContext);
+ when(contextSpy.getSystemService(UsbManager.class)).thenReturn(mUsbManager);
+ when(contextSpy.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)))
+ .thenReturn(new Intent(Intent.ACTION_BATTERY_CHANGED));
+ return contextSpy;
+ }
+
+ private Intent getBatteryIntent() {
+ return new Intent(Intent.ACTION_BATTERY_CHANGED).putExtra(
+ BatteryManager.EXTRA_HEALTH, BatteryManager.BATTERY_HEALTH_OVERHEAT);
+ }
+
private class TestableKeyguardUpdateMonitor extends KeyguardUpdateMonitor {
AtomicBoolean mSimStateChanged = new AtomicBoolean(false);