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
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user