Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d7391e70 authored by YK Hung's avatar YK Hung Committed by Android (Google) Code Review
Browse files

Merge "Add incompatible charging state on the lockscreen"

parents d6825722 97ca1050
Loading
Loading
Loading
Loading
+30 −6
Original line number Diff line number Diff line
@@ -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;
    }
}
+3 −0
Original line number Diff line number Diff line
@@ -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>

+24 −6
Original line number Diff line number Diff line
@@ -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;
        }

+6 −0
Original line number Diff line number Diff line
@@ -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;
+94 −4
Original line number Diff line number Diff line
@@ -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);