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

Commit cdd1bb2f authored by Sherry Huang's avatar Sherry Huang Committed by android-build-merger
Browse files

Merge "SystemUI: overheat warning enhancements and bug fixes." into qt-dev

am: 4645ba6e

Change-Id: Ifede0d83d1c6efe55a1f9096ca19aa26a1e80cab
parents ad643225 4645ba6e
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -353,7 +353,6 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
        if (!mHighTempWarning) {
            return;
        }
        mHighTempWarning = false;
        dismissHighTemperatureWarningInternal();
    }

@@ -364,6 +363,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
     */
    private void dismissHighTemperatureWarningInternal() {
        mNoMan.cancelAsUser(TAG_TEMPERATURE, SystemMessage.NOTE_HIGH_TEMP, UserHandle.ALL);
        mHighTempWarning = false;
    }

    @Override
+99 −43
Original line number Diff line number Diff line
@@ -23,11 +23,9 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.os.BatteryManager;
import android.os.Handler;
import android.os.IBinder;
import android.os.IThermalEventListener;
import android.os.IThermalService;
import android.os.PowerManager;
@@ -95,6 +93,9 @@ public class PowerUI extends SystemUI {
    @VisibleForTesting int mBatteryLevel = 100;
    @VisibleForTesting int mBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN;

    private IThermalEventListener mSkinThermalEventListener;
    private IThermalEventListener mUsbThermalEventListener;

    public void start() {
        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
        mScreenOffTime = mPowerManager.isScreenOn() ? -1 : SystemClock.elapsedRealtime();
@@ -119,7 +120,29 @@ public class PowerUI extends SystemUI {
        // to the temperature being too high.
        showThermalShutdownDialog();

        initTemperature();
        // Register an observer to configure mEnableSkinTemperatureWarning and perform the
        // registration of skin thermal event listener upon Settings change.
        resolver.registerContentObserver(
                Settings.Global.getUriFor(Settings.Global.SHOW_TEMPERATURE_WARNING),
                false /*notifyForDescendants*/,
                new ContentObserver(mHandler) {
                    @Override
                    public void onChange(boolean selfChange) {
                        doSkinThermalEventListenerRegistration();
                    }
                });
        // Register an observer to configure mEnableUsbTemperatureAlarm and perform the
        // registration of usb thermal event listener upon Settings change.
        resolver.registerContentObserver(
                Settings.Global.getUriFor(Settings.Global.SHOW_USB_TEMPERATURE_ALARM),
                false /*notifyForDescendants*/,
                new ContentObserver(mHandler) {
                    @Override
                    public void onChange(boolean selfChange) {
                        doUsbThermalEventListenerRegistration();
                    }
                });
        initThermalEventListeners();
    }

    @Override
@@ -128,7 +151,7 @@ public class PowerUI extends SystemUI {

        // Safe to modify mLastConfiguration here as it's only updated by the main thread (here).
        if ((mLastConfiguration.updateFrom(newConfig) & mask) != 0) {
            mHandler.post(this::initTemperature);
            mHandler.post(this::initThermalEventListeners);
        }
    }

@@ -444,45 +467,78 @@ public class PowerUI extends SystemUI {
                        && currentSnapshot.getBucket() > 0);
    }

    private void initTemperature() {
        ContentResolver resolver = mContext.getContentResolver();
        Resources resources = mContext.getResources();
    private void initThermalEventListeners() {
        doSkinThermalEventListenerRegistration();
        doUsbThermalEventListenerRegistration();
    }

    @VisibleForTesting
    synchronized void doSkinThermalEventListenerRegistration() {
        final boolean oldEnableSkinTemperatureWarning = mEnableSkinTemperatureWarning;
        boolean ret = false;

        mEnableSkinTemperatureWarning = Settings.Global.getInt(resolver,
        mEnableSkinTemperatureWarning = Settings.Global.getInt(mContext.getContentResolver(),
            Settings.Global.SHOW_TEMPERATURE_WARNING,
                resources.getInteger(R.integer.config_showTemperatureWarning)) != 0;
        mEnableUsbTemperatureAlarm = Settings.Global.getInt(resolver,
                Settings.Global.SHOW_USB_TEMPERATURE_ALARM,
                resources.getInteger(R.integer.config_showUsbPortAlarm)) != 0;
            mContext.getResources().getInteger(R.integer.config_showTemperatureWarning)) != 0;

        if (mEnableSkinTemperatureWarning != oldEnableSkinTemperatureWarning) {
            try {
                if (mSkinThermalEventListener == null) {
                    mSkinThermalEventListener = new SkinThermalEventListener();
                }
                if (mThermalService == null) {
            // Enable push notifications of throttling from vendor thermal
            // management subsystem via thermalservice, in addition to our
            // usual polling, to react to temperature jumps more quickly.
            IBinder b = ServiceManager.getService(Context.THERMAL_SERVICE);

            if (b != null) {
                mThermalService = IThermalService.Stub.asInterface(b);
                registerThermalEventListener();
                    mThermalService = IThermalService.Stub.asInterface(
                        ServiceManager.getService(Context.THERMAL_SERVICE));
                }
                if (mEnableSkinTemperatureWarning) {
                    ret = mThermalService.registerThermalEventListenerWithType(
                            mSkinThermalEventListener, Temperature.TYPE_SKIN);
                } else {
                Slog.w(TAG, "cannot find thermalservice, no throttling push notifications");
                    ret = mThermalService.unregisterThermalEventListener(mSkinThermalEventListener);
                }
            } catch (RemoteException e) {
                Slog.e(TAG, "Exception while (un)registering skin thermal event listener.", e);
            }

            if (!ret) {
                mEnableSkinTemperatureWarning = !mEnableSkinTemperatureWarning;
                Slog.e(TAG, "Failed to register or unregister skin thermal event listener.");
            }
        }
    }

    @VisibleForTesting
    void registerThermalEventListener() {
    synchronized void doUsbThermalEventListenerRegistration() {
        final boolean oldEnableUsbTemperatureAlarm = mEnableUsbTemperatureAlarm;
        boolean ret = false;

        mEnableUsbTemperatureAlarm = Settings.Global.getInt(mContext.getContentResolver(),
            Settings.Global.SHOW_USB_TEMPERATURE_ALARM,
            mContext.getResources().getInteger(R.integer.config_showUsbPortAlarm)) != 0;

        if (mEnableUsbTemperatureAlarm != oldEnableUsbTemperatureAlarm) {
            try {
            if (mEnableSkinTemperatureWarning) {
                mThermalService.registerThermalEventListenerWithType(
                        new ThermalEventSkinListener(), Temperature.TYPE_SKIN);
                if (mUsbThermalEventListener == null) {
                    mUsbThermalEventListener = new UsbThermalEventListener();
                }
                if (mThermalService == null) {
                    mThermalService = IThermalService.Stub.asInterface(
                        ServiceManager.getService(Context.THERMAL_SERVICE));
                }
                if (mEnableUsbTemperatureAlarm) {
                mThermalService.registerThermalEventListenerWithType(
                        new ThermalEventUsbListener(), Temperature.TYPE_USB_PORT);
                    ret = mThermalService.registerThermalEventListenerWithType(
                            mUsbThermalEventListener, Temperature.TYPE_USB_PORT);
                } else {
                    ret = mThermalService.unregisterThermalEventListener(mUsbThermalEventListener);
                }
            } catch (RemoteException e) {
            Slog.e(TAG, "Failed to register thermal callback.", e);
                Slog.e(TAG, "Exception while (un)registering usb thermal event listener.", e);
            }

            if (!ret) {
                mEnableUsbTemperatureAlarm = !mEnableUsbTemperatureAlarm;
                Slog.e(TAG, "Failed to register or unregister usb thermal event listener.");
            }
        }
    }

@@ -558,7 +614,7 @@ public class PowerUI extends SystemUI {
        void showHighTemperatureWarning();

        /**
         * Display USB overheat alarm
         * Display USB port overheat alarm
         */
        void showUsbHighTemperatureAlarm();

@@ -575,9 +631,9 @@ public class PowerUI extends SystemUI {
        void updateSnapshot(BatteryStateSnapshot snapshot);
    }

    // Thermal event received from thermal service manager subsystem
    // Skin thermal event received from thermal service manager subsystem
    @VisibleForTesting
    final class ThermalEventSkinListener extends IThermalEventListener.Stub {
    final class SkinThermalEventListener extends IThermalEventListener.Stub {
        @Override public void notifyThrottling(Temperature temp) {
            int status = temp.getStatus();

@@ -585,7 +641,7 @@ public class PowerUI extends SystemUI {
                StatusBar statusBar = getComponent(StatusBar.class);
                if (statusBar != null && !statusBar.isDeviceInVrMode()) {
                    mWarnings.showHighTemperatureWarning();
                    Slog.d(TAG, "ThermalEventSkinListener: notifyThrottling was called "
                    Slog.d(TAG, "SkinThermalEventListener: notifyThrottling was called "
                            + ", current skin status = " + status
                            + ", temperature = " + temp.getValue());
                }
@@ -595,15 +651,15 @@ public class PowerUI extends SystemUI {
        }
    }

    // Thermal event received from thermal service manager subsystem
    // Usb thermal event received from thermal service manager subsystem
    @VisibleForTesting
    final class ThermalEventUsbListener extends IThermalEventListener.Stub {
    final class UsbThermalEventListener extends IThermalEventListener.Stub {
        @Override public void notifyThrottling(Temperature temp) {
            int status = temp.getStatus();

            if (status >= Temperature.THROTTLING_EMERGENCY) {
                mWarnings.showUsbHighTemperatureAlarm();
                Slog.d(TAG, "ThermalEventUsbListener: notifyThrottling was called "
                Slog.d(TAG, "UsbThermalEventListener: notifyThrottling was called "
                        + ", current usb port status = " + status
                        + ", temperature = " + temp.getValue());
            }
+160 −13
Original line number Diff line number Diff line
@@ -46,15 +46,15 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.power.PowerUI.WarningsUI;
import com.android.systemui.statusbar.phone.StatusBar;

import java.time.Duration;
import java.util.concurrent.TimeUnit;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.time.Duration;
import java.util.concurrent.TimeUnit;

@RunWith(AndroidTestingRunner.class)
@RunWithLooper
@SmallTest
@@ -78,8 +78,8 @@ public class PowerUITest extends SysuiTestCase {
    private EnhancedEstimates mEnhancedEstimates;
    @Mock private PowerManager mPowerManager;
    @Mock private IThermalService mThermalServiceMock;
    private IThermalEventListener mThermalEventUsbListener;
    private IThermalEventListener mThermalEventSkinListener;
    private IThermalEventListener mUsbThermalEventListener;
    private IThermalEventListener mSkinThermalEventListener;

    @Before
    public void setup() {
@@ -91,8 +91,8 @@ public class PowerUITest extends SysuiTestCase {
        mContext.addMockSystemService(Context.POWER_SERVICE, mPowerManager);

        createPowerUi();
        mThermalEventSkinListener = mPowerUI.new ThermalEventSkinListener();
        mThermalEventUsbListener = mPowerUI.new ThermalEventUsbListener();
        mSkinThermalEventListener = mPowerUI.new SkinThermalEventListener();
        mUsbThermalEventListener = mPowerUI.new UsbThermalEventListener();
    }

    @Test
@@ -100,7 +100,7 @@ public class PowerUITest extends SysuiTestCase {
        mPowerUI.start();

        final Temperature temp = getCriticalStatusTemp(Temperature.TYPE_SKIN, "skin1");
        mThermalEventSkinListener.notifyThrottling(temp);
        mSkinThermalEventListener.notifyThrottling(temp);

        // dismiss skin high temperature warning when throttling status is critical
        TestableLooper.get(this).processAllMessages();
@@ -113,7 +113,7 @@ public class PowerUITest extends SysuiTestCase {
        mPowerUI.start();

        final Temperature temp = getEmergencyStatusTemp(Temperature.TYPE_SKIN, "skin2");
        mThermalEventSkinListener.notifyThrottling(temp);
        mSkinThermalEventListener.notifyThrottling(temp);

        // show skin high temperature warning when throttling status is emergency
        TestableLooper.get(this).processAllMessages();
@@ -126,7 +126,7 @@ public class PowerUITest extends SysuiTestCase {
        mPowerUI.start();

        final Temperature temp = getCriticalStatusTemp(Temperature.TYPE_USB_PORT, "usb1");
        mThermalEventUsbListener.notifyThrottling(temp);
        mUsbThermalEventListener.notifyThrottling(temp);

        // not show usb high temperature alarm when throttling status is critical
        TestableLooper.get(this).processAllMessages();
@@ -138,7 +138,7 @@ public class PowerUITest extends SysuiTestCase {
        mPowerUI.start();

        final Temperature temp = getEmergencyStatusTemp(Temperature.TYPE_USB_PORT, "usb2");
        mThermalEventUsbListener.notifyThrottling(temp);
        mUsbThermalEventListener.notifyThrottling(temp);

        // show usb high temperature alarm when throttling status is emergency
        TestableLooper.get(this).processAllMessages();
@@ -152,7 +152,6 @@ public class PowerUITest extends SysuiTestCase {
        resources.addOverride(R.integer.config_showTemperatureWarning, 0);

        mPowerUI.start();
        mPowerUI.registerThermalEventListener();

        TestableLooper.get(this).processAllMessages();
        verify(mThermalServiceMock, times(1))
@@ -166,13 +165,161 @@ public class PowerUITest extends SysuiTestCase {
        resources.addOverride(R.integer.config_showUsbPortAlarm, 0);

        mPowerUI.start();
        mPowerUI.registerThermalEventListener();

        TestableLooper.get(this).processAllMessages();
        verify(mThermalServiceMock, times(1))
                .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_USB_PORT));
    }

    @Test
    public void testSettingOverrideConfig_disableSkinTemperatureWarning() throws Exception {
        Settings.Global.putInt(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, 0);
        TestableResources resources = mContext.getOrCreateTestableResources();
        resources.addOverride(R.integer.config_showTemperatureWarning, 1);

        mPowerUI.start();

        TestableLooper.get(this).processAllMessages();
        verify(mThermalServiceMock, times(0))
                .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_SKIN));
    }

    @Test
    public void testSettingOverrideConfig_disableUsbTemperatureAlarm() throws Exception {
        Settings.Global.putInt(mContext.getContentResolver(), SHOW_USB_TEMPERATURE_ALARM, 0);
        TestableResources resources = mContext.getOrCreateTestableResources();
        resources.addOverride(R.integer.config_showUsbPortAlarm, 1);

        mPowerUI.start();

        TestableLooper.get(this).processAllMessages();
        verify(mThermalServiceMock, times(0))
                .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_USB_PORT));
    }

    @Test
    public void testThermalEventListenerRegistration_success_skinType() throws Exception {
        // Settings SHOW_TEMPERATURE_WARNING is set to 1
        Settings.Global.putInt(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, 1);

        // success registering skin thermal event listener
        when(mThermalServiceMock.registerThermalEventListenerWithType(
                anyObject(), eq(Temperature.TYPE_SKIN))).thenReturn(true);

        mPowerUI.doSkinThermalEventListenerRegistration();

        // verify registering skin thermal event listener, return true (success)
        TestableLooper.get(this).processAllMessages();
        verify(mThermalServiceMock, times(1))
                .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_SKIN));

        // Settings SHOW_TEMPERATURE_WARNING is set to 0
        Settings.Global.putInt(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, 0);

        mPowerUI.doSkinThermalEventListenerRegistration();

        // verify unregistering skin thermal event listener
        TestableLooper.get(this).processAllMessages();
        verify(mThermalServiceMock, times(1)).unregisterThermalEventListener(anyObject());
    }

    @Test
    public void testThermalEventListenerRegistration_fail_skinType() throws Exception {
        // Settings SHOW_TEMPERATURE_WARNING is set to 1
        Settings.Global.putInt(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, 1);

        // fail registering skin thermal event listener
        when(mThermalServiceMock.registerThermalEventListenerWithType(
                anyObject(), eq(Temperature.TYPE_SKIN))).thenReturn(false);

        mPowerUI.doSkinThermalEventListenerRegistration();

        // verify registering skin thermal event listener, return false (fail)
        TestableLooper.get(this).processAllMessages();
        verify(mThermalServiceMock, times(1))
                .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_SKIN));

        // Settings SHOW_TEMPERATURE_WARNING is set to 0
        Settings.Global.putInt(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, 0);

        mPowerUI.doSkinThermalEventListenerRegistration();

        // verify that cannot unregister listener (current state is unregistered)
        TestableLooper.get(this).processAllMessages();
        verify(mThermalServiceMock, times(0)).unregisterThermalEventListener(anyObject());

        // Settings SHOW_TEMPERATURE_WARNING is set to 1
        Settings.Global.putInt(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, 1);

        mPowerUI.doSkinThermalEventListenerRegistration();

        // verify that can register listener (current state is unregistered)
        TestableLooper.get(this).processAllMessages();
        verify(mThermalServiceMock, times(2))
                .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_SKIN));
    }

    @Test
    public void testThermalEventListenerRegistration_success_usbType() throws Exception {
        // Settings SHOW_USB_TEMPERATURE_ALARM is set to 1
        Settings.Global.putInt(mContext.getContentResolver(), SHOW_USB_TEMPERATURE_ALARM, 1);

        // success registering usb thermal event listener
        when(mThermalServiceMock.registerThermalEventListenerWithType(
                anyObject(), eq(Temperature.TYPE_USB_PORT))).thenReturn(true);

        mPowerUI.doUsbThermalEventListenerRegistration();

        // verify registering usb thermal event listener, return true (success)
        TestableLooper.get(this).processAllMessages();
        verify(mThermalServiceMock, times(1))
                .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_USB_PORT));

        // Settings SHOW_USB_TEMPERATURE_ALARM is set to 0
        Settings.Global.putInt(mContext.getContentResolver(), SHOW_USB_TEMPERATURE_ALARM, 0);

        // verify unregistering usb thermal event listener
        mPowerUI.doUsbThermalEventListenerRegistration();
        TestableLooper.get(this).processAllMessages();
        verify(mThermalServiceMock, times(1)).unregisterThermalEventListener(anyObject());
    }

    @Test
    public void testThermalEventListenerRegistration_fail_usbType() throws Exception {
        // Settings SHOW_USB_TEMPERATURE_ALARM is set to 1
        Settings.Global.putInt(mContext.getContentResolver(), SHOW_USB_TEMPERATURE_ALARM, 1);

        // fail registering usb thermal event listener
        when(mThermalServiceMock.registerThermalEventListenerWithType(
                anyObject(), eq(Temperature.TYPE_USB_PORT))).thenReturn(false);

        mPowerUI.doUsbThermalEventListenerRegistration();

        // verify registering usb thermal event listener, return false (fail)
        TestableLooper.get(this).processAllMessages();
        verify(mThermalServiceMock, times(1))
                .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_USB_PORT));

        // Settings SHOW_USB_TEMPERATURE_ALARM is set to 0
        Settings.Global.putInt(mContext.getContentResolver(), SHOW_USB_TEMPERATURE_ALARM, 0);

        mPowerUI.doUsbThermalEventListenerRegistration();

        // verify that cannot unregister listener (current state is unregistered)
        TestableLooper.get(this).processAllMessages();
        verify(mThermalServiceMock, times(0)).unregisterThermalEventListener(anyObject());

        // Settings SHOW_USB_TEMPERATURE_ALARM is set to 1
        Settings.Global.putInt(mContext.getContentResolver(), SHOW_USB_TEMPERATURE_ALARM, 1);

        mPowerUI.doUsbThermalEventListenerRegistration();

        // verify that can register listener (current state is unregistered)
        TestableLooper.get(this).processAllMessages();
        verify(mThermalServiceMock, times(2)).registerThermalEventListenerWithType(
                anyObject(), eq(Temperature.TYPE_USB_PORT));
    }

    @Test
    public void testMaybeShowHybridWarning() {
        mPowerUI.start();