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

Commit 5eeb8e58 authored by Alexander Hofbauer's avatar Alexander Hofbauer
Browse files

Support devices with amber/green LEDs.

On devices like the Legend HTC used a binary amber/green LED with
support for hardware blinking.
Both colors on at the same time result in a slightly lighter amber that
is not distinguishable from amber at all. So we have to make sure their
status is mutual exclusive.

I decided to use amber as charging and battery low indicator and green
for notifications. Green always overrides amber.

Change-Id: Id4e8a1cd7a2be217b5cf4c5b45b1fc5beba5d2db
parent 120cb783
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -2015,6 +2015,27 @@ public final class Settings {
         */
        public static final String NOTIFICATION_LIGHT_PULSE = "notification_light_pulse";

        /**
         * Whether the notification LED should repeatedly blink when a notification is
         * pending. The value is boolean (1 or 0).
         * @hide
         */
        public static final String NOTIFICATION_LIGHT_BLINK = "notification_light_blink";

        /**
         * Whether to show turn off the notification LED (and charging light
         * off) when screen is on. The value is boolean (1 or 0).
         * @hide
         */
        public static final String NOTIFICATION_LIGHT_ALWAYS_ON = "notification_light_always_on";

        /**
         * Whether to turn on the amber LED while charging (and notifications light off).
         * The value is boolean (1 or 0).
         * @hide
         */
        public static final String NOTIFICATION_LIGHT_CHARGING = "notification_light_charging";

        /**
         * Show pointer location on screen?
         * 0 = no
@@ -2301,6 +2322,9 @@ public final class Settings {
            LOCKSCREEN_SOUNDS_ENABLED,
            SHOW_WEB_SUGGESTIONS,
            NOTIFICATION_LIGHT_PULSE,
            NOTIFICATION_LIGHT_BLINK,
            NOTIFICATION_LIGHT_ALWAYS_ON,
            NOTIFICATION_LIGHT_CHARGING,
            HAPTIC_FEEDBACK_UP_ENABLED,
            HAPTIC_FEEDBACK_ALL_ENABLED,
            HAPTIC_DOWN_ARRAY,
+3 −0
Original line number Diff line number Diff line
@@ -327,4 +327,7 @@
    <!-- This is known to cause issues on certain platforms -->
    <bool name="config_gps_xtra_download_on_boot">true</bool>

    <!-- Handle notifications differently if device only uses an amber/green
    LED. This also needs a liblights module that enables them accordingly. -->
    <bool name="config_amber_green_light">false</bool>
</resources>
+161 −17
Original line number Diff line number Diff line
@@ -113,6 +113,8 @@ class NotificationManagerService extends INotificationManager.Stub {

    private int mDefaultNotificationLedOff;

    private boolean mAmberGreenLight;

    private NotificationRecord mSoundNotification;

    private NotificationPlayer mSound;
@@ -132,6 +134,14 @@ class NotificationManagerService extends INotificationManager.Stub {

    private boolean mNotificationPulseEnabled;

    private boolean mNotificationBlinkEnabled;

    private boolean mNotificationAlwaysOnEnabled;

    private boolean mNotificationChargingEnabled;

    private boolean mGreenLightOn = false;

    // for adb connected notifications
    private boolean mUsbConnected;

@@ -384,7 +394,11 @@ class NotificationManagerService extends INotificationManager.Stub {
                    mBatteryCharging = batteryCharging;
                    mBatteryLow = batteryLow;
                    mBatteryFull = batteryFull;
                    updateLights();
                    if (mAmberGreenLight) {
                        updateAmberLight();
                    } else {
                        updateRGBLights();
                    }
                }
            } else if (action.equals(Intent.ACTION_UMS_CONNECTED)) {
                mUsbConnected = true;
@@ -421,26 +435,45 @@ class NotificationManagerService extends INotificationManager.Stub {
                }
            } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
                mScreenOn = true;
                if (mAmberGreenLight) {
                    if (!mNotificationAlwaysOnEnabled) {
                        updateGreenLight();
                    }
                } else {
                    int mPulseScreen = Settings.System.getInt(mContext.getContentResolver(),
                            Settings.System.TRACKBALL_SCREEN_ON, 0);
                    if (mPulseScreen == 0) { // Why bother if we are going to pulse
                                             // anyways?
                        updateNotificationPulse();
                    }
                }

            } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
                mScreenOn = false;
                if (mAmberGreenLight) {
                    if (!mNotificationAlwaysOnEnabled) {
                        updateGreenLight();
                    }
                } else {
                    int mPulseScreen = Settings.System.getInt(mContext.getContentResolver(),
                            Settings.System.TRACKBALL_SCREEN_ON, 0);
                    if (mPulseScreen == 0) { // Why bother if we are going to pulse
                                             // anyways?
                        updateNotificationPulse();
                    }
                }
            } else if (action.equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) {
                mInCall = (intent.getStringExtra(TelephonyManager.EXTRA_STATE)
                        .equals(TelephonyManager.EXTRA_STATE_OFFHOOK));
                if (mAmberGreenLight) {
                    if (mInCall) {
                        updateGreenLight();
                    }
                } else {
                    updateNotificationPulse();
                }
            }
        }
    };

    class SettingsObserver extends ContentObserver {
@@ -454,6 +487,12 @@ class NotificationManagerService extends INotificationManager.Stub {
                    Settings.Secure.getUriFor(Settings.Secure.ADB_ENABLED), false, this);
            resolver.registerContentObserver(Settings.System
                    .getUriFor(Settings.System.NOTIFICATION_LIGHT_PULSE), false, this);
            resolver.registerContentObserver(Settings.System
                    .getUriFor(Settings.System.NOTIFICATION_LIGHT_BLINK), false, this);
            resolver.registerContentObserver(Settings.System
                    .getUriFor(Settings.System.NOTIFICATION_LIGHT_ALWAYS_ON), false, this);
            resolver.registerContentObserver(Settings.System
                    .getUriFor(Settings.System.NOTIFICATION_LIGHT_CHARGING), false, this);
            resolver.registerContentObserver(Settings.System
                    .getUriFor(Settings.System.QUIET_HOURS_ENABLED), false, this);
            resolver.registerContentObserver(Settings.System
@@ -488,6 +527,24 @@ class NotificationManagerService extends INotificationManager.Stub {
                mNotificationPulseEnabled = pulseEnabled;
                updateNotificationPulse();
            }
            boolean blinkEnabled = Settings.System.getInt(resolver,
                    Settings.System.NOTIFICATION_LIGHT_BLINK, 0) != 0;
            if (mNotificationBlinkEnabled != blinkEnabled) {
                mNotificationBlinkEnabled = blinkEnabled;
                updateLights();
            }
            boolean alwaysOnEnabled = Settings.System.getInt(resolver,
                    Settings.System.NOTIFICATION_LIGHT_ALWAYS_ON, 0) != 0;
            if (mNotificationAlwaysOnEnabled != alwaysOnEnabled) {
                mNotificationAlwaysOnEnabled = alwaysOnEnabled;
                updateLights();
            }
            boolean chargingEnabled = Settings.System.getInt(resolver,
                    Settings.System.NOTIFICATION_LIGHT_CHARGING, 0) != 0;
            if (mNotificationChargingEnabled != chargingEnabled) {
                mNotificationChargingEnabled = chargingEnabled;
                updateAmberLight();
            }

            mQuietHoursEnabled = Settings.System.getInt(resolver,
                    Settings.System.QUIET_HOURS_ENABLED, 0) != 0;
@@ -526,6 +583,8 @@ class NotificationManagerService extends INotificationManager.Stub {
                .getInteger(com.android.internal.R.integer.config_defaultNotificationLedOn);
        mDefaultNotificationLedOff = resources
                .getInteger(com.android.internal.R.integer.config_defaultNotificationLedOff);
        mAmberGreenLight = resources
                .getBoolean(com.android.internal.R.bool.config_amber_green_light);

        // Don't start allowing notifications until the setup wizard has run
        // once.
@@ -947,13 +1006,26 @@ class NotificationManagerService extends INotificationManager.Stub {
    private boolean checkLight(Notification notification, String pkg) {
        String[] mPackage = findPackage(pkg);
        boolean flashLight = true;

        boolean noLight = false;
        if (mAmberGreenLight) {
            if ((notification.flags & Notification.FLAG_SHOW_LIGHTS) == 0) {
                noLight = true;
            }
        } else {
            if (((notification.flags & Notification.FLAG_ONGOING_EVENT) != 0)
                    || ((notification.flags & Notification.FLAG_FOREGROUND_SERVICE) != 0)) {
                noLight = true;
            }
        }

        if (noLight) {
            flashLight = false;
        } else if (mPackage != null) {
            if (mPackage[1].equals("none"))
            if (mPackage[1].equals("none")) {
                flashLight = false;
            }
        }
        return flashLight;
    }

@@ -1149,6 +1221,18 @@ class NotificationManagerService extends INotificationManager.Stub {
        }
    }

    private void updateRGBLights() {
        synchronized (mNotificationList) {
            updateRGBLightsLocked();
        }
    }

    private void updateGreenLight() {
        synchronized (mNotificationList) {
            updateGreenLightLocked();
        }
    }

    public boolean isNull(String mString) {
        if (mString == null || mString.matches("null") || mString.length() == 0
                || mString.matches("|") || mString.matches("")) {
@@ -1180,8 +1264,9 @@ class NotificationManagerService extends INotificationManager.Stub {
        String mBaseString = Settings.System.getString(mContext.getContentResolver(),
                Settings.System.NOTIFICATION_PACKAGE_COLORS);
        String[] mBaseArray = getArray(mBaseString);
        if (mBaseArray == null)
        if (mBaseArray == null) {
            return null;
        }
        for (int i = 0; i < mBaseArray.length; i++) {
            if (isNull(mBaseArray[i])) {
                continue;
@@ -1255,8 +1340,9 @@ class NotificationManagerService extends INotificationManager.Stub {
            int x = generator.nextInt(colorList.length - 1);
            rledARGB = Color.parseColor(colorList[x]);
        } else if (mPulseAllColor == 1) {
            if (lastColor >= colorList.length)
            if (lastColor >= colorList.length) {
                lastColor = 1;
            }

            rledARGB = Color.parseColor(colorList[lastColor - 1]);
            lastColor = lastColor + 1;
@@ -1300,6 +1386,14 @@ class NotificationManagerService extends INotificationManager.Stub {

    // lock on mNotificationList
    private void updateLightsLocked() {
        if (mAmberGreenLight) {
            updateGreenLightLocked();
        } else {
            updateRGBLightsLocked();
        }
    }

    private void updateRGBLightsLocked() {
        int mPulseScreen = Settings.System.getInt(mContext.getContentResolver(),
                Settings.System.TRACKBALL_SCREEN_ON, 0);
        int mSuccession = Settings.System.getInt(mContext.getContentResolver(),
@@ -1429,6 +1523,56 @@ class NotificationManagerService extends INotificationManager.Stub {
        }
    }

    private void updateGreenLightLocked() {
        // handle notification light
        if (mLedNotification == null) {
            // get next notification, if any
            int n = mLights.size();
            if (n > 0) {
                mLedNotification = mLights.get(n - 1);
            }
        }

        boolean greenOn = mGreenLightOn;
        final boolean inQuietHours = inQuietHours();

        // disable light if screen is on and "always show" is off
        if (mLedNotification == null || mInCall || inQuietHours
                || (mScreenOn && !mNotificationAlwaysOnEnabled)) {
            mNotificationLight.turnOff();
            mGreenLightOn = false;
        } else {
            if (mNotificationBlinkEnabled) {
                mNotificationLight.setFlashing(0xFF00FF00,
                        LightsService.LIGHT_FLASH_HARDWARE, 0, 0);

            } else {
                mNotificationLight.setColor(0xFF00FF00);
            }
            mGreenLightOn = true;
        }

        if (greenOn != mGreenLightOn) {
            updateAmberLight();
        }
    }

    private void updateAmberLight() {
        // disable LED if green LED is already on
        if (!mGreenLightOn && !mInCall) {
            final boolean inQuietHours = inQuietHours();

            // enable amber only if low battery and not charging or charging
            // and notification enabled
            if (!inQuietHours && ((mBatteryLow && !mBatteryCharging) ||
                    (mBatteryCharging && mNotificationChargingEnabled && !mBatteryFull))) {
                mBatteryLight.setColor(0xFFFFFF00);
                return;
            }
        }
        mBatteryLight.turnOff();
    }

    // lock on mNotificationList
    private int indexOfNotificationLocked(String pkg, String tag, int id) {
        ArrayList<NotificationRecord> list = mNotificationList;