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

Unverified Commit b802d842 authored by Sam Mortimer's avatar Sam Mortimer Committed by Michael Bestas
Browse files

frameworks/base: Battery and Notification Lights



Co-authored-by: default avatarAdnan Begovic <adnan@cyngn.com>
Co-authored-by: default avatarAdrian DC <radian.dc@gmail.com>
Co-authored-by: Alexander Martinz's avatarAlexander Martinz <amartinz@shiftphones.com>
Co-authored-by: default avatarAltaf-Mahdi <altaf.mahdi@gmail.com>
Co-authored-by: default avatarDanesh M <daneshm90@gmail.com>
Co-authored-by: default avatarDvTonder <david.vantonder@gmail.com>
Co-authored-by: default avatarLuca Stefani <luca.stefani.ge1@gmail.com>
Co-authored-by: default avatarMichael Bestas <mikeioannina@gmail.com>
Co-authored-by: default avatarMichael W <baddaemon87@gmail.com>
Co-authored-by: default avatarPawit Pornkitprasan <p.pawit@gmail.com>
Co-authored-by: default avatarSteve Kondik <steve@cyngn.com>
Change-Id: I564fdb6ca6c5bbcf890afa4b9a2f9fa7bf8b9604
parent 8024044f
Loading
Loading
Loading
Loading
+46 −35
Original line number Diff line number Diff line
@@ -73,6 +73,9 @@ import com.android.server.health.HealthServiceWrapper;
import com.android.server.lights.LightsManager;
import com.android.server.lights.LogicalLight;

import org.lineageos.internal.notification.LedValues;
import org.lineageos.internal.notification.LineageBatteryLights;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
@@ -226,6 +229,8 @@ public final class BatteryService extends SystemService {

    private MetricsLogger mMetricsLogger;

    private LineageBatteryLights mLineageBatteryLights;

    public BatteryService(Context context) {
        super(context);

@@ -301,6 +306,16 @@ public final class BatteryService extends SystemService {
                        false, obs, UserHandle.USER_ALL);
                updateBatteryWarningLevelLocked();
            }
        } else if (phase == PHASE_BOOT_COMPLETED) {
            mLineageBatteryLights = new LineageBatteryLights(mContext,
                    new LineageBatteryLights.LedUpdater() {
                public void update() {
                    updateLedPulse();
                }
            });

            // Update light state now that mLineageBatteryLights has been initialized.
            updateLedPulse();
        }
    }

@@ -1307,6 +1322,10 @@ public final class BatteryService extends SystemService {
        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
    }

    private synchronized void updateLedPulse() {
        mLed.updateLightsLocked();
    }

    private final class Led {
        // must match: config_notificationsBatteryLowBehavior in config.xml
        static final int LOW_BATTERY_BEHAVIOR_DEFAULT = 0;
@@ -1348,43 +1367,35 @@ public final class BatteryService extends SystemService {
            if (mBatteryLight == null) {
                return;
            }
            final int level = mHealthInfo.batteryLevel;
            final int status = mHealthInfo.batteryStatus;
            if (level < mLowBatteryWarningLevel) {
                switch (mBatteryLowBehavior) {
                    case LOW_BATTERY_BEHAVIOR_SOLID:
                        // Solid red when low battery
                        mBatteryLight.setColor(mBatteryLowARGB);
                        break;
                    case LOW_BATTERY_BEHAVIOR_FLASHING:
                        // Flash red when battery is low and not charging
                        mBatteryLight.setFlashing(mBatteryLowARGB, LogicalLight.LIGHT_FLASH_TIMED,
                                mBatteryLedOn, mBatteryLedOff);
                        break;
                    default:
                        if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
                            // Solid red when battery is charging
                            mBatteryLight.setColor(mBatteryLowARGB);
                        } else {
                            // Flash red when battery is low and not charging
                            mBatteryLight.setFlashing(mBatteryLowARGB,
                                    LogicalLight.LIGHT_FLASH_TIMED, mBatteryLedOn, mBatteryLedOff);
            // mHealthInfo could be null on startup (called by SettingsObserver)
            if (mHealthInfo == null) {
                Slog.w(TAG, "updateLightsLocked: mHealthInfo is null; skipping");
                return;
            }
                        break;
            // mLineageBatteryLights is initialized during PHASE_BOOT_COMPLETED
            // This means we don't have Lineage battery settings yet so skip.
            if (mLineageBatteryLights == null) {
                if (DEBUG) {
                    Slog.w(TAG, "updateLightsLocked: mLineageBatteryLights is not yet ready; "
                            + "skipping");
                }
            } else if (status == BatteryManager.BATTERY_STATUS_CHARGING
                    || status == BatteryManager.BATTERY_STATUS_FULL) {
                if (status == BatteryManager.BATTERY_STATUS_FULL
                        || level >= mBatteryNearlyFullLevel) {
                    // Solid green when full or charging and nearly full
                    mBatteryLight.setColor(mBatteryFullARGB);
                } else {
                    // Solid orange when charging and halfway full
                    mBatteryLight.setColor(mBatteryMediumARGB);
                return;
            }
            } else {
                // No lights if not charging and not low
            if (!mLineageBatteryLights.isSupported()) {
                return;
            }

            LedValues ledValues = new LedValues(0 /* color */, mBatteryLedOn, mBatteryLedOff);
            mLineageBatteryLights.calcLights(ledValues, mHealthInfo.batteryLevel,
                    mHealthInfo.batteryStatus, mHealthInfo.batteryLevel <= mLowBatteryWarningLevel);

            if (!ledValues.isEnabled()) {
                mBatteryLight.turnOff();
            } else if (ledValues.isPulsed()) {
                mBatteryLight.setFlashing(ledValues.getColor(), LogicalLight.LIGHT_FLASH_TIMED,
                        ledValues.getOnMs(), ledValues.getOffMs());
            } else {
                mBatteryLight.setColor(ledValues.getColor());
            }
        }
    }
+68 −19
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 * Copyright (C) 2015 The CyanogenMod Project
 * Copyright (C) 2017 The LineageOS Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
@@ -79,6 +81,9 @@ import com.android.server.EventLogTags;
import com.android.server.lights.LightsManager;
import com.android.server.lights.LogicalLight;

import org.lineageos.internal.notification.LedValues;
import org.lineageos.internal.notification.LineageNotificationLights;

import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -160,6 +165,7 @@ public final class NotificationAttentionHelper {
    private final float mInCallNotificationVolume;
    private Binder mCallNotificationToken = null;
    private final ArrayMap<String, Long> mLastSoundTimestamps = new ArrayMap<>();
    private LineageNotificationLights mLineageNotificationLights;

    // Settings flags
    private boolean mNotificationCooldownEnabled;
@@ -212,6 +218,22 @@ public final class NotificationAttentionHelper {
                .build();
        mInCallNotificationVolume = resources.getFloat(R.dimen.config_inCallNotificationVolume);

        mLineageNotificationLights = new LineageNotificationLights(mContext,
                 new LineageNotificationLights.LedUpdater() {
            public void update() {
                updateLightsLocked();
            }
        });

        mZenModeHelper.addCallback(new ZenModeHelper.Callback() {
            @Override
            void onZenModeChanged() {
                Binder.withCleanCallingIdentity(() -> {
                    mLineageNotificationLights.setZenMode(mZenModeHelper.getZenMode());
                });
            }
        });

        if (Flags.politeNotifications()) {
            mStrategy = createPolitenessStrategy();
        } else {
@@ -861,10 +883,12 @@ public final class NotificationAttentionHelper {
    }

    private void clearLightsLocked() {
        // light
        // clear only if lockscreen is not active
        if (!mLineageNotificationLights.isKeyguardLocked()) {
            mLights.clear();
            updateLightsLocked();
        }
    }

    public void clearEffectsLocked(String key) {
        if (key.equals(mSoundNotificationKey)) {
@@ -901,19 +925,43 @@ public final class NotificationAttentionHelper {
            }
        }

        // Don't flash while we are in a call or screen is on
        if (ledNotification == null || isInCall() || mScreenOn) {
        NotificationRecord.Light light = ledNotification != null ?
                ledNotification.getLight() : null;
        if (ledNotification == null || mLineageNotificationLights == null || light == null) {
            mNotificationLight.turnOff();
            return;
        }

        int ledColor = light.color;
        if (isLedForcedOn(ledNotification) && ledColor == 0) {
            // User has requested color 0.  However, lineage-sdk interprets
            // color 0 as "supply a default" therefore adjust alpha to make
            // the color still black but non-zero.
            ledColor = 0x01000000;
        }

        LedValues ledValues = new LedValues(ledColor, light.onMs, light.offMs);
        mLineageNotificationLights.calcLights(ledValues, ledNotification.getSbn().getPackageName(),
                ledNotification.getSbn().getNotification(), mScreenOn || isInCall(),
                ledNotification.getSuppressedVisualEffects());

        if (!ledValues.isEnabled()) {
            mNotificationLight.turnOff();
        } else {
            NotificationRecord.Light light = ledNotification.getLight();
            if (light != null && mNotificationPulseEnabled) {
                // pulse repeatedly
                mNotificationLight.setFlashing(light.color, LogicalLight.LIGHT_FLASH_TIMED,
                        light.onMs, light.offMs);
            // we are using 1:0 to indicate LED should stay always on
            if (ledValues.getOnMs() == 1 && ledValues.getOffMs() == 0) {
                mNotificationLight.setColor(ledValues.getColor());
            } else {
                mNotificationLight.setFlashing(ledValues.getColor(),
                        LogicalLight.LIGHT_FLASH_TIMED, ledValues.getOnMs(), ledValues.getOffMs());
            }
        }
    }

    private boolean isLedForcedOn(NotificationRecord nr) {
        return nr != null && mLineageNotificationLights.isForcedOn(nr.getSbn().getNotification());
    }

    boolean canShowLightsLocked(final NotificationRecord record, final Signals signals,
            boolean aboveThreshold) {
        if (!mSystemReady) {
@@ -923,6 +971,12 @@ public final class NotificationAttentionHelper {
        if (!mHasLight) {
            return false;
        }
        // Forced on
        // Used by LineageParts light picker
        // eg to allow selecting battery light color when notification led is turned off.
        if (isLedForcedOn(record)) {
            return true;
        }
        // user turned lights off globally
        if (!mNotificationPulseEnabled) {
            return false;
@@ -935,10 +989,6 @@ public final class NotificationAttentionHelper {
        if (!aboveThreshold) {
            return false;
        }
        // suppressed due to DND
        if ((record.getSuppressedVisualEffects() & SUPPRESSED_EFFECT_LIGHTS) != 0) {
            return false;
        }
        // Suppressed because it's a silent update
        final Notification notification = record.getNotification();
        if (record.isUpdate && (notification.flags & FLAG_ONLY_ALERT_ONCE) != 0) {
@@ -948,10 +998,6 @@ public final class NotificationAttentionHelper {
        if (record.getSbn().isGroup() && record.getNotification().suppressAlertingDueToGrouping()) {
            return false;
        }
        // not if in call
        if (isInCall()) {
            return false;
        }
        // check current user
        if (!isNotificationForCurrentUser(record, signals)) {
            return false;
@@ -1640,8 +1686,11 @@ public final class NotificationAttentionHelper {
                mUserPresent = true;
                // turn off LED when user passes through lock screen
                if (mNotificationLight != null) {
                    // if lights with screen on is disabled.
                    if (!mLineageNotificationLights.showLightsScreenOn()) {
                        mNotificationLight.turnOff();
                    }
                }
            } else if (action.equals(Intent.ACTION_USER_ADDED)
                        || action.equals(Intent.ACTION_USER_REMOVED)
                        || action.equals(Intent.ACTION_USER_SWITCHED)
+2 −2
Original line number Diff line number Diff line
@@ -283,8 +283,8 @@ public final class NotificationRecord {
    }

    private Light calculateLights() {
        int defaultLightColor = mContext.getResources().getColor(
                com.android.internal.R.color.config_defaultNotificationColor);
        // Lineage lights will set the default color later
        int defaultLightColor = 0;
        int defaultLightOn = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_defaultNotificationLedOn);
        int defaultLightOff = mContext.getResources().getInteger(