Doze: Add plugin hook
Test: mmm vendor/google_experimental/users/roosa/DozePlugin/ Change-Id: I7ea55954f0c07be932e8ee7037e03b7c01cc1108
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ public class DozeService extends DreamService implements DozeMachine.Service {
|
||||
|
||||
setWindowless(true);
|
||||
|
||||
mDozeMachine = DozeFactory.assembleMachine(this);
|
||||
mDozeMachine = DozeFactory.getInstance(getApplication()).assembleMachine(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -58,6 +58,7 @@ public class DozeTriggers implements DozeMachine.Part {
|
||||
private final SensorManager mSensorManager;
|
||||
private final Handler mHandler;
|
||||
private final DozeFactory.WakeLock mWakeLock;
|
||||
private final boolean mAllowPulseTriggers;
|
||||
private final UiModeManager mUiModeManager;
|
||||
private final TriggerReceiver mBroadcastReceiver = new TriggerReceiver();
|
||||
|
||||
@@ -68,7 +69,7 @@ public class DozeTriggers implements DozeMachine.Part {
|
||||
public DozeTriggers(Context context, DozeMachine machine, DozeHost dozeHost,
|
||||
AmbientDisplayConfiguration config,
|
||||
DozeParameters dozeParameters, SensorManager sensorManager, Handler handler,
|
||||
DozeFactory.WakeLock wakeLock) {
|
||||
DozeFactory.WakeLock wakeLock, boolean allowPulseTriggers) {
|
||||
mContext = context;
|
||||
mMachine = machine;
|
||||
mDozeHost = dozeHost;
|
||||
@@ -77,6 +78,7 @@ public class DozeTriggers implements DozeMachine.Part {
|
||||
mSensorManager = sensorManager;
|
||||
mHandler = handler;
|
||||
mWakeLock = wakeLock;
|
||||
mAllowPulseTriggers = allowPulseTriggers;
|
||||
mDozeSensors = new DozeSensors(context, mSensorManager, dozeParameters, config,
|
||||
wakeLock, this::onSensor);
|
||||
mUiModeManager = mContext.getSystemService(UiModeManager.class);
|
||||
@@ -149,7 +151,7 @@ public class DozeTriggers implements DozeMachine.Part {
|
||||
|
||||
private void requestPulse(final int reason, boolean performedProxCheck) {
|
||||
Assert.isMainThread();
|
||||
if (mPulsePending || !canPulse()) {
|
||||
if (mPulsePending || !mAllowPulseTriggers || !canPulse()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -306,20 +308,11 @@ public class DozeTriggers implements DozeMachine.Part {
|
||||
}
|
||||
|
||||
private DozeHost.Callback mHostCallback = new DozeHost.Callback() {
|
||||
@Override
|
||||
public void onNewNotifications() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBuzzBeepBlinked() {
|
||||
onNotification();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNotificationLight(boolean on) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPowerSaveChanged(boolean active) {
|
||||
if (active) {
|
||||
|
||||
@@ -5167,5 +5167,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|
||||
return mNotificationLightOn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startPendingIntentDismissingKeyguard(PendingIntent intent) {
|
||||
PhoneStatusBar.this.startPendingIntentDismissingKeyguard(intent);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user