diff options
5 files changed, 157 insertions, 16 deletions
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java index e0588ee9cfeb..2555e2b7eb9c 100644 --- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java +++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java @@ -34,6 +34,8 @@ import android.os.BatteryManager; import com.android.settingslib.R; +import java.util.Optional; + /** * Stores and computes some battery information. */ @@ -52,11 +54,12 @@ public class BatteryStatus { public final int health; public final int maxChargingWattage; public final boolean present; + public final Optional<Boolean> incompatibleCharger; - public static BatteryStatus create(Context context) { + public static BatteryStatus create(Context context, boolean incompatibleCharger) { final Intent batteryChangedIntent = BatteryUtils.getBatteryIntent(context); return batteryChangedIntent == null - ? null : new BatteryStatus(batteryChangedIntent); + ? null : new BatteryStatus(batteryChangedIntent, incompatibleCharger); } public BatteryStatus(int status, int level, int plugged, int health, @@ -67,14 +70,25 @@ public class BatteryStatus { this.health = health; this.maxChargingWattage = maxChargingWattage; this.present = present; + this.incompatibleCharger = Optional.empty(); } + public BatteryStatus(Intent batteryChangedIntent) { + this(batteryChangedIntent, Optional.empty()); + } + + public BatteryStatus(Intent batteryChangedIntent, boolean incompatibleCharger) { + this(batteryChangedIntent, Optional.of(incompatibleCharger)); + } + + private BatteryStatus(Intent batteryChangedIntent, Optional<Boolean> incompatibleCharger) { status = batteryChangedIntent.getIntExtra(EXTRA_STATUS, BATTERY_STATUS_UNKNOWN); plugged = batteryChangedIntent.getIntExtra(EXTRA_PLUGGED, 0); level = getBatteryLevel(batteryChangedIntent); health = batteryChangedIntent.getIntExtra(EXTRA_HEALTH, BATTERY_HEALTH_UNKNOWN); present = batteryChangedIntent.getBooleanExtra(EXTRA_PRESENT, true); + this.incompatibleCharger = incompatibleCharger; final int maxChargingMicroAmp = batteryChangedIntent.getIntExtra(EXTRA_MAX_CHARGING_CURRENT, -1); @@ -95,10 +109,7 @@ public class BatteryStatus { /** Determine whether the device is plugged. */ public boolean isPluggedIn() { - return plugged == BatteryManager.BATTERY_PLUGGED_AC - || plugged == BatteryManager.BATTERY_PLUGGED_USB - || plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS - || plugged == BatteryManager.BATTERY_PLUGGED_DOCK; + return isPluggedIn(plugged); } /** Determine whether the device is plugged in (USB, power). */ @@ -190,4 +201,17 @@ public class BatteryStatus { ? -1 /*invalid battery level*/ : Math.round((level / (float) scale) * 100f); } + + /** Whether the device is plugged or not. */ + public static boolean isPluggedIn(Intent batteryChangedIntent) { + return isPluggedIn(batteryChangedIntent.getIntExtra(EXTRA_PLUGGED, 0)); + } + + /** Whether the device is plugged or not. */ + public static boolean isPluggedIn(int plugged) { + return plugged == BatteryManager.BATTERY_PLUGGED_AC + || plugged == BatteryManager.BATTERY_PLUGGED_USB + || plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS + || plugged == BatteryManager.BATTERY_PLUGGED_DOCK; + } } diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml index f4cef84724e4..51f507cfeddb 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 9f1c382353e0..5b628f81ed73 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; 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.internal.widget.LockPatternUtils; 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 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab // Battery status @VisibleForTesting BatteryStatus mBatteryStatus; + @VisibleForTesting + boolean mIncompatibleCharger; private StrongAuthTracker mStrongAuthTracker; @@ -1572,10 +1576,20 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab 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 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab 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 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab 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 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab 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 250900e3e931..d3927a28bb38 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 @@ public class KeyguardIndicationController { 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 @@ public class KeyguardIndicationController { 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 @@ public class KeyguardIndicationController { 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 4110b5a9f7d4..841ec4b8c76f 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.face.FaceSensorPropertiesInternal; 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.ILockSettings; 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 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { 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 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { @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 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { 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 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { 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 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { 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); |