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

Commit 95cb7777 authored by Sam Mortimer's avatar Sam Mortimer
Browse files

LineageParts: Add notification brightness dialog

*) In the past, we added our brightness dialog to SystemUI.

*) Move and rework it here in LineageParts to shrink frameworks changes.

Adapted from the original frameworks/base commit:

Author: Adrian DC <radian.dc@gmail.com>
Date:   Tue Aug 18 19:33:18 2015 +0200
    frameworks/base: Lights notifications brightness support
    Implement the support of an overall brightness control for the LEDs.
    Change-Id: I1c0de01b1c6a2a2cf1432028a2e69f90b2373b2c

Change-Id: I425cc0747fe477d285d34eb2155565670bebf509
parent 15eb2133
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
<!--
Copyright (C) 2014 The Android Open Source Project

   Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="28.0dp"
        android:height="28.0dp"
        android:viewportWidth="24.0"
        android:viewportHeight="24.0">
    <path
        android:pathData="m18.250000,12.000000a6.250000,6.250000 0.000000,1.000000 1.000000,-12.500000 0.000000,6.250000 6.250000,0.000000 1.000000,1.000000 12.500000,0.000000z"
        android:fillColor="?android:attr/colorPrimary" />
    <path
        android:fillColor="?android:attr/colorControlNormal"
        android:pathData="M20.000000,8.700000L20.000000,4.000000L15.300000,4.000000L12.000000,0.700000 8.700000,4.000000L4.000000,4.000000L4.000000,8.700000L0.700000,12.000000 4.000000,15.300000L4.000000,20.000000L8.700000,20.000000L12.000000,23.299999 15.300000,20.000000L20.000000,20.000000L20.000000,15.300000L23.299999,12.000000 20.000000,8.700000zM12.000000,18.000000C8.700000,18.000000 6.000000,15.300000 6.000000,12.000000 6.000000,8.700000 8.700000,6.000000 12.000000,6.000000c3.300000,0.000000 6.000000,2.700000 6.000000,6.000000 0.000000,3.300000 -2.700000,6.000000 -6.000000,6.000000zM12.000000,8.000000c-2.200000,0.000000 -4.000000,1.800000 -4.000000,4.000000 0.000000,2.200000 1.800000,4.000000 4.000000,4.000000 2.200000,0.000000 4.000000,-1.800000 4.000000,-4.000000 0.000000,-2.200000 -1.800000,-4.000000 -4.000000,-4.000000z"/>
</vector>
+29 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2012-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.
     You may obtain a copy of the License at

          http://www.apache.org/licenses/LICENSE-2.0

     Unless required by applicable law or agreed to in writing, software
     distributed under the License is distributed on an "AS IS" BASIS,
     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     See the License for the specific language governing permissions and
     limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:paddingLeft="16dp"
    android:paddingRight="16dp">

    <SeekBar
        android:id="@+id/notification_brightness_seekbar"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_weight="1"
        android:paddingTop="20dp" />

</LinearLayout>
+2 −4
Original line number Diff line number Diff line
@@ -44,12 +44,10 @@
        android:key="advanced_section"
        android:title="@string/advanced">

        <PreferenceScreen
        <org.lineageos.lineageparts.notificationlight.NotificationBrightnessDialog
            android:key="notification_light_brightness_level"
            android:title="@string/notification_light_brightness"
            android:dependency="notification_light_pulse">
            <intent android:action="android.intent.action.SHOW_NOTIFICATION_BRIGHTNESS_DIALOG" />
        </PreferenceScreen>
            android:dependency="notification_light_pulse" />

        <lineageos.preference.LineageSystemSettingSwitchPreference
            android:key="notification_light_screen_on_enable"
+272 −0
Original line number Diff line number Diff line
/*
 * 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.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.lineageos.lineageparts.notificationlight;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.UserHandle;
import android.support.v7.preference.Preference;
import android.util.AttributeSet;
import android.view.View;
import android.widget.SeekBar;

import lineageos.providers.LineageSettings;

import org.lineageos.internal.notification.LightsCapabilities;
import org.lineageos.lineageparts.widget.CustomDialogPreference;
import org.lineageos.lineageparts.R;

public class NotificationBrightnessDialog extends CustomDialogPreference<AlertDialog>
        implements SeekBar.OnSeekBarChangeListener {

    private static String TAG = "NotificationBrightnessDialog";

    public static final int LIGHT_BRIGHTNESS_MINIMUM = 1;
    public static final int LIGHT_BRIGHTNESS_MAXIMUM = 255;

    // Minimum delay between LED notification updates
    private final static long LED_UPDATE_DELAY_MS = 250;

    private SeekBar mBrightnessBar;

    // The user selected brightness level (past or present if dialog is OKed).
    private int mSelectedBrightness;
    // Current position of brightness seekbar
    private int mSeekBarBrightness;
    // LED brightness currently on display (0 means notification is not showing)
    private int mVisibleLedBrightness;

    private final Context mContext;
    private final Handler mHandler;

    private final Notification.Builder mNotificationBuilder;
    private NotificationManager mNotificationManager;

    public NotificationBrightnessDialog(Context context, AttributeSet attrs) {
        super(context, attrs);

        setDialogLayoutResource(R.layout.notification_brightness_dialog);

        mContext = context;

        // Message handler used for led notification update throttling.
        mHandler = new Handler();

        mNotificationManager =
                (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

        Bundle bundle = new Bundle();
        bundle.putBoolean(Notification.EXTRA_FORCE_SHOW_LIGHTS, true);

        mNotificationBuilder = new Notification.Builder(mContext);
        mNotificationBuilder.setExtras(bundle)
                .setContentTitle(mContext.getString(R.string.led_notification_title))
                .setContentText(mContext.getString(R.string.led_notification_text))
                .setSmallIcon(R.drawable.ic_settings_24dp)
                .setOngoing(true);
    }

    @Override
    protected void onPrepareDialogBuilder(AlertDialog.Builder builder, DialogInterface.OnClickListener listener) {
        super.onPrepareDialogBuilder(builder, listener);
        // Set no-op handler for RESET button (note, the reset itself is handled in onDismissDialog())
        builder.setNeutralButton(R.string.reset,
                new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
            }
        });
    }

    @Override
    protected boolean onDismissDialog(AlertDialog dialog, int which) {
        if (which == DialogInterface.BUTTON_NEUTRAL) {
            // Reset brightness to default (max).
            mBrightnessBar.setProgress(LIGHT_BRIGHTNESS_MAXIMUM);
            return false;
        }
        return true;
    }

    @Override
    protected void onDialogClosed(boolean positiveResult) {
        super.onDialogClosed(positiveResult);

        if (positiveResult) {
            mSelectedBrightness = mSeekBarBrightness;
        } else {
            mSeekBarBrightness = mSelectedBrightness;
        }
    }

    @Override
    protected void onBindDialogView(View view) {
        super.onBindDialogView(view);

        updateSelectedBrightness();
        mSeekBarBrightness = mSelectedBrightness;
        mVisibleLedBrightness = 0; // LED notification is not showing.

        mBrightnessBar = (SeekBar) view.findViewById(R.id.notification_brightness_seekbar);
        mBrightnessBar.setMax(LIGHT_BRIGHTNESS_MAXIMUM);
        mBrightnessBar.setMin(LIGHT_BRIGHTNESS_MINIMUM);
        mBrightnessBar.setOnSeekBarChangeListener(this);
        mBrightnessBar.setProgress(mSeekBarBrightness);
        mBrightnessBar.setThumb(mContext.getResources().getDrawable(
                R.drawable.ic_brightness_thumb, mContext.getTheme()));
    }

    @Override
    protected void onResume() {
        // Get current notification brightness setting.
        updateSelectedBrightness();

        // Set maximum system brightness so that the notification preview
        // is relative to the real maximum.
        LineageSettings.System.putIntForUser(mContext.getContentResolver(),
                LineageSettings.System.NOTIFICATION_LIGHT_BRIGHTNESS_LEVEL,
                LIGHT_BRIGHTNESS_MAXIMUM, UserHandle.USER_CURRENT);

        updateNotification();
    }

    @Override
    protected void onPause() {
        cancelNotification();
        // Restore original or save new brightness
        LineageSettings.System.putIntForUser(mContext.getContentResolver(),
                LineageSettings.System.NOTIFICATION_LIGHT_BRIGHTNESS_LEVEL,
                mSelectedBrightness, UserHandle.USER_CURRENT);
    }

    @Override
    public void onStartTrackingTouch (SeekBar seekBar) {}

    @Override
    public void onStopTrackingTouch (SeekBar seekBar) {}

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        mSeekBarBrightness = progress;
        updateNotification();
    }

    private void updateSelectedBrightness() {
        mSelectedBrightness = LineageSettings.System.getIntForUser(mContext.getContentResolver(),
                LineageSettings.System.NOTIFICATION_LIGHT_BRIGHTNESS_LEVEL,
                LIGHT_BRIGHTNESS_MAXIMUM, UserHandle.USER_CURRENT);
    }

    private void updateNotification() {
        // Exit if there's nothing to do or we're throttled.
        if (mVisibleLedBrightness == mSeekBarBrightness || mLedHandler.hasMessages(0)) {
            return;
        }

        mLedHandler.sendEmptyMessageDelayed(0, LED_UPDATE_DELAY_MS);

        // Instead of canceling the notification, force it to update with the color.
        // Use a white light for a better preview of the brightness.
        int notificationColor = 0xFFFFFF | (mSeekBarBrightness << 24);
        mNotificationBuilder.setLights(notificationColor, 1, 0);
        mNotificationManager.notify(1, mNotificationBuilder.build());
        mVisibleLedBrightness = mSeekBarBrightness;
    }

    private void cancelNotification() {
        if (mVisibleLedBrightness > 0) {
            mLedHandler.removeMessages(0);
            mNotificationManager.cancel(1);
            mVisibleLedBrightness = 0;
        }
    }

    private Handler mLedHandler = new Handler() {
        public void handleMessage(Message msg) {
            updateNotification();
        }
    };

    @Override
    protected Parcelable onSaveInstanceState() {
        final Parcelable superState = super.onSaveInstanceState();
        if (getDialog() == null || !getDialog().isShowing()) {
            return superState;
        }

        // Save the dialog state
        final SavedState myState = new SavedState(superState);
        myState.seekBarBrightness = mSeekBarBrightness;

        return myState;
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        if (state == null || !state.getClass().equals(SavedState.class)) {
            // Didn't save state for us in onSaveInstanceState
            super.onRestoreInstanceState(state);
            return;
        }

        SavedState myState = (SavedState) state;
        super.onRestoreInstanceState(myState.getSuperState());

        mSeekBarBrightness = myState.seekBarBrightness;
    }

    private static class SavedState extends BaseSavedState {
        int seekBarBrightness;

        public SavedState(Parcelable superState) {
            super(superState);
        }

        public SavedState(Parcel source) {
            super(source);
            seekBarBrightness = source.readInt();
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            super.writeToParcel(dest, flags);
            dest.writeInt(seekBarBrightness);
        }

        public static final Parcelable.Creator<SavedState> CREATOR =
                new Parcelable.Creator<SavedState>() {

            public SavedState createFromParcel(Parcel in) {
                return new SavedState(in);
            }

            public SavedState[] newArray(int size) {
                return new SavedState[size];
            }
        };
    }
}
+3 −6
Original line number Diff line number Diff line
@@ -74,7 +74,7 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem
    private int mDefaultLedOff;
    private PackageManager mPackageManager;
    private PreferenceGroup mApplicationPrefList;
    private PreferenceScreen mNotificationLedBrightnessPref;
    private NotificationBrightnessDialog mNotificationBrightnessDialog;
    private SystemSettingSwitchPreference mEnabledPref;
    private LineageSystemSettingSwitchPreference mCustomEnabledPref;
    private LineageSystemSettingSwitchPreference mScreenOnLightsPref;
@@ -128,7 +128,7 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem
                findPreference(LineageSettings.System.NOTIFICATION_LIGHT_COLOR_AUTO);

        // Advanced light settings
        mNotificationLedBrightnessPref = (PreferenceScreen)
        mNotificationBrightnessDialog = (NotificationBrightnessDialog)
                findPreference(LineageSettings.System.NOTIFICATION_LIGHT_BRIGHTNESS_LEVEL);
        mScreenOnLightsPref = (LineageSystemSettingSwitchPreference)
                findPreference(LineageSettings.System.NOTIFICATION_LIGHT_SCREEN_ON);
@@ -137,9 +137,7 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem
                findPreference(LineageSettings.System.NOTIFICATION_LIGHT_PULSE_CUSTOM_ENABLE);
        if (!LightsCapabilities.supports(
                context, LightsCapabilities.LIGHTS_ADJUSTABLE_NOTIFICATION_LED_BRIGHTNESS)) {
            mAdvancedPrefs.removePreference(mNotificationLedBrightnessPref);
        } else {
            mNotificationLedBrightnessPref.setOnPreferenceChangeListener(this);
            mAdvancedPrefs.removePreference(mNotificationBrightnessDialog);
        }
        if (!mLedCanPulse && !mMultiColorLed) {
            mGeneralPrefs.removePreference(mDefaultPref);
@@ -457,7 +455,6 @@ public class NotificationLightSettings extends SettingsPreferenceFragment implem

    public boolean onPreferenceChange(Preference preference, Object objValue) {
        if (preference == mEnabledPref || preference == mCustomEnabledPref ||
                preference == mNotificationLedBrightnessPref ||
                preference == mScreenOnLightsPref ||
                preference == mAutoGenerateColors) {
            getActivity().invalidateOptionsMenu();