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

Commit 7317467c authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Doze: Add plugin hook"

parents 5cdf4934 f9d13f6d
Loading
Loading
Loading
Loading
+39 −0
Original line number Diff line number Diff line
@@ -267,6 +267,45 @@ public class NotificationColorUtil {
        return ColorUtilsFromCompat.LABToColor(low, a, b);
    }

    /**
     * Finds a suitable color such that there's enough contrast.
     *
     * @param color the color to start searching from.
     * @param other the color to ensure contrast against. Assumed to be darker than {@param color}
     * @param findFg if true, we assume {@param color} is a foreground, otherwise a background.
     * @param minRatio the minimum contrast ratio required.
     * @return a color with the same hue as {@param color}, potentially darkened to meet the
     *          contrast ratio.
     */
    public static int findContrastColorAgainstDark(int color, int other, boolean findFg,
            double minRatio) {
        int fg = findFg ? color : other;
        int bg = findFg ? other : color;
        if (ColorUtilsFromCompat.calculateContrast(fg, bg) >= minRatio) {
            return color;
        }

        double[] lab = new double[3];
        ColorUtilsFromCompat.colorToLAB(findFg ? fg : bg, lab);

        double low = lab[0], high = 100;
        final double a = lab[1], b = lab[2];
        for (int i = 0; i < 15 && high - low > 0.00001; i++) {
            final double l = (low + high) / 2;
            if (findFg) {
                fg = ColorUtilsFromCompat.LABToColor(l, a, b);
            } else {
                bg = ColorUtilsFromCompat.LABToColor(l, a, b);
            }
            if (ColorUtilsFromCompat.calculateContrast(fg, bg) > minRatio) {
                high = l;
            } else {
                low = l;
            }
        }
        return ColorUtilsFromCompat.LABToColor(high, a, b);
    }

    /**
     * Finds a text color with sufficient contrast over bg that has the same hue as the original
     * color, assuming it is for large text.
+100 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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.
 */

package com.android.systemui.plugins.doze;

import android.app.PendingIntent;
import android.content.Context;

import com.android.systemui.plugins.Plugin;

/**
 * Provides a {@link DozeUi}.
 */
public interface DozeProvider extends Plugin {

    String ACTION = "com.android.systemui.action.PLUGIN_DOZE";
    int VERSION = 1;

    /**
     * Caution: Even if this is called, the DozeUi provided may still be in use until it transitions
     * to DozeState.FINISH
     */
    @Override
    default void onDestroy() {
    }

    /**
     * @return the plugin's implementation of DozeUi.
     */
    DozeUi provideDozeUi(Context context, DozeMachine machine, WakeLock wakeLock);

    /**
     * If true, the plugin allows the default pulse triggers to fire, otherwise they are disabled.
     */
    default boolean allowDefaultPulseTriggers() {
        return false;
    }

    /**
     * Ui for use in DozeMachine.
     */
    interface DozeUi {
        /** Called whenever the DozeMachine state transitions */
        void transitionTo(DozeState oldState, DozeState newState);
    }

    /** WakeLock wrapper for testability */
    interface WakeLock {
        /** @see android.os.PowerManager.WakeLock#acquire() */
        void acquire();
        /** @see android.os.PowerManager.WakeLock#release() */
        void release();
        /** @see android.os.PowerManager.WakeLock#wrap(Runnable) */
        Runnable wrap(Runnable r);
    }

    /** Plugin version of the DozeMachine's state */
    enum DozeState {
        /** Default state. Transition to INITIALIZED to get Doze going. */
        UNINITIALIZED,
        /** Doze components are set up. Followed by transition to DOZE or DOZE_AOD. */
        INITIALIZED,
        /** Regular doze. Device is asleep and listening for pulse triggers. */
        DOZE,
        /** Always-on doze. Device is asleep, showing UI and listening for pulse triggers. */
        DOZE_AOD,
        /** Pulse has been requested. Device is awake and preparing UI */
        DOZE_REQUEST_PULSE,
        /** Pulse is showing. Device is awake and showing UI. */
        DOZE_PULSING,
        /** Pulse is done showing. Followed by transition to DOZE or DOZE_AOD. */
        DOZE_PULSE_DONE,
        /** Doze is done. DozeService is finished. */
        FINISH,
        /** WakeUp. */
        WAKE_UP,
    }

    /** Plugin interface for the doze machine. */
    interface DozeMachine {
        /** Request that the DozeMachine transitions to {@code state} */
        void requestState(DozeState state);

        /** Request that the PendingIntent is sent. */
        void requestSendIntent(PendingIntent intent);
    }
}
+3 −1
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import android.os.SystemProperties;
import android.os.UserHandle;
import android.util.Log;

import com.android.systemui.doze.DozeFactory;
import com.android.systemui.fragments.FragmentService;
import com.android.systemui.keyboard.KeyboardUI;
import com.android.systemui.keyguard.KeyguardViewMediator;
@@ -76,7 +77,8 @@ public class SystemUIApplication extends Application {
            PipUI.class,
            ShortcutKeyDispatcher.class,
            VendorServices.class,
            LatencyTester.class
            LatencyTester.class,
            DozeFactory.Initializer.class,
    };

    /**
+136 −5
Original line number Diff line number Diff line
@@ -17,19 +17,52 @@
package com.android.systemui.doze;

import android.app.Application;
import android.app.PendingIntent;
import android.content.Context;
import android.hardware.SensorManager;
import android.os.Handler;
import android.os.PowerManager;
import android.os.SystemClock;

import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.systemui.SystemUI;
import com.android.systemui.SystemUIApplication;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.PluginManager;
import com.android.systemui.plugins.doze.DozeProvider;
import com.android.systemui.statusbar.phone.DozeParameters;

public class DozeFactory {

    private static DozeFactory sInstance;

    private DozeProvider mDozePlugin;

    /** Returns the singleton instance. */
    public static DozeFactory getInstance(Context context) {
        if (sInstance == null) {
            sInstance = new DozeFactory();
            PluginManager.getInstance(context).addPluginListener(DozeProvider.ACTION,
                    new PluginListener<DozeProvider>() {
                        @Override
                        public void onPluginConnected(DozeProvider plugin) {
                            sInstance.mDozePlugin = plugin;
                        }

                        @Override
                        public void onPluginDisconnected(DozeProvider plugin) {
                            if (sInstance.mDozePlugin == plugin) {
                                sInstance.mDozePlugin = null;
                            }
                        }
                    },
                    DozeProvider.VERSION, false /* Only one */);
        }
        return sInstance;
    }

    /** Creates a DozeMachine with its parts for {@code dozeService}. */
    public static DozeMachine assembleMachine(DozeService dozeService) {
    public DozeMachine assembleMachine(DozeService dozeService) {
        Context context = dozeService;
        SensorManager sensorManager = context.getSystemService(SensorManager.class);
        PowerManager powerManager = context.getSystemService(PowerManager.class);
@@ -43,14 +76,103 @@ public class DozeFactory {

        DozeMachine machine = new DozeMachine(dozeService, params, wakeLock);
        machine.setParts(new DozeMachine.Part[]{
                new DozeTriggers(context, machine, host, config, params,
                        sensorManager, handler, wakeLock),
                new DozeUi(context, machine, wakeLock, host),
                createDozeTriggers(context, sensorManager, host, config, params, handler, wakeLock,
                        machine),
                createDozeUi(context, host, wakeLock, machine),
        });

        return machine;
    }

    private DozeTriggers createDozeTriggers(Context context, SensorManager sensorManager,
            DozeHost host, AmbientDisplayConfiguration config, DozeParameters params,
            Handler handler, WakeLock wakeLock, DozeMachine machine) {
        boolean allowPulseTriggers = mDozePlugin == null || mDozePlugin.allowDefaultPulseTriggers();
        return new DozeTriggers(context, machine, host, config, params,
                sensorManager, handler, wakeLock, allowPulseTriggers);
    }

    private DozeMachine.Part createDozeUi(Context context, DozeHost host, WakeLock wakeLock,
            DozeMachine machine) {
        if (mDozePlugin != null) {
            DozeProvider.DozeUi dozeUi = mDozePlugin.provideDozeUi(context,
                    pluginMachine(context, machine, host),
                    wakeLock);
            return (oldState, newState) -> {
                dozeUi.transitionTo(pluginState(oldState),
                        pluginState(newState));
            };
        } else {
            return new DozeUi(context, machine, wakeLock, host);
        }
    }

    private DozeProvider.DozeMachine pluginMachine(Context context, DozeMachine machine,
            DozeHost host) {
        return new DozeProvider.DozeMachine() {
            @Override
            public void requestState(DozeProvider.DozeState state) {
                if (state == DozeProvider.DozeState.WAKE_UP) {
                    PowerManager pm = context.getSystemService(PowerManager.class);
                    pm.wakeUp(SystemClock.uptimeMillis(), "com.android.systemui:NODOZE");
                    return;
                }
                machine.requestState(implState(state));
            }

            @Override
            public void requestSendIntent(PendingIntent intent) {
                host.startPendingIntentDismissingKeyguard(intent);
            }
        };
    }

    private DozeMachine.State implState(DozeProvider.DozeState s) {
        switch (s) {
            case UNINITIALIZED:
                return DozeMachine.State.UNINITIALIZED;
            case INITIALIZED:
                return DozeMachine.State.INITIALIZED;
            case DOZE:
                return DozeMachine.State.DOZE;
            case DOZE_AOD:
                return DozeMachine.State.DOZE_AOD;
            case DOZE_REQUEST_PULSE:
                return DozeMachine.State.DOZE_REQUEST_PULSE;
            case DOZE_PULSING:
                return DozeMachine.State.DOZE_PULSING;
            case DOZE_PULSE_DONE:
                return DozeMachine.State.DOZE_PULSE_DONE;
            case FINISH:
                return DozeMachine.State.FINISH;
            default:
                throw new IllegalArgumentException("Unknown state: " + s);
        }
    }

    private DozeProvider.DozeState pluginState(DozeMachine.State s) {
        switch (s) {
            case UNINITIALIZED:
                return DozeProvider.DozeState.UNINITIALIZED;
            case INITIALIZED:
                return DozeProvider.DozeState.INITIALIZED;
            case DOZE:
                return DozeProvider.DozeState.DOZE;
            case DOZE_AOD:
                return DozeProvider.DozeState.DOZE_AOD;
            case DOZE_REQUEST_PULSE:
                return DozeProvider.DozeState.DOZE_REQUEST_PULSE;
            case DOZE_PULSING:
                return DozeProvider.DozeState.DOZE_PULSING;
            case DOZE_PULSE_DONE:
                return DozeProvider.DozeState.DOZE_PULSE_DONE;
            case FINISH:
                return DozeProvider.DozeState.FINISH;
            default:
                throw new IllegalArgumentException("Unknown state: " + s);
        }
    }

    private static DozeHost getHost(DozeService service) {
        Application appCandidate = service.getApplication();
        final SystemUIApplication app = (SystemUIApplication) appCandidate;
@@ -58,7 +180,7 @@ public class DozeFactory {
    }

    /** A wrapper around {@link PowerManager.WakeLock} for testability. */
    public static class WakeLock {
    public static class WakeLock implements DozeProvider.WakeLock {
        private final PowerManager.WakeLock mInner;

        public WakeLock(PowerManager.WakeLock inner) {
@@ -80,4 +202,13 @@ public class DozeFactory {
            return mInner.wrap(runnable);
        }
    }

    /** Hack: We need to initialize the plugin listener before doze actually starts.
     * This will be unnecessary once we have proper one-shot support */
    public static class Initializer extends SystemUI {
        @Override
        public void start() {
            getInstance(mContext);
        }
    }
}
+9 −6
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.systemui.doze;

import android.annotation.NonNull;
import android.app.PendingIntent;

/**
 * Interface the doze service uses to communicate with the rest of system UI.
@@ -32,14 +33,16 @@ public interface DozeHost {
    boolean isNotificationLightOn();
    boolean isPulsingBlocked();

    public interface Callback {
        void onNewNotifications();
        void onBuzzBeepBlinked();
        void onNotificationLight(boolean on);
        void onPowerSaveChanged(boolean active);
    void startPendingIntentDismissingKeyguard(PendingIntent intent);

    interface Callback {
        default void onNewNotifications() {}
        default void onBuzzBeepBlinked() {}
        default void onNotificationLight(boolean on) {}
        default void onPowerSaveChanged(boolean active) {}
    }

    public interface PulseCallback {
    interface PulseCallback {
        void onPulseStarted();
        void onPulseFinished();
    }
Loading