AOD: Refactor doze brigthness controllers, add AOD auto brightness support

- Factor out doze brightness and screen state controllers
- Add support for setting the screen brightness from a
  sensor in AOD / when pulsing
- Refactor FakeSensorManager for generic sensors, add a light sensor

Bug: 38354633
Test: runtest -x packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenTest.java
Change-Id: I55f2bee253cee23a76ba857ba1f19052ff88a753
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index 1cc10c2..53a8be5 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -19,10 +19,12 @@
 import android.app.AlarmManager;
 import android.app.Application;
 import android.content.Context;
+import android.hardware.Sensor;
 import android.hardware.SensorManager;
 import android.os.Handler;
 
 import com.android.internal.hardware.AmbientDisplayConfiguration;
+import com.android.systemui.R;
 import com.android.systemui.SystemUIApplication;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.util.wakelock.DelayedWakeLock;
@@ -46,20 +48,31 @@
         WakeLock wakeLock = new DelayedWakeLock(handler,
                 WakeLock.createPartial(context, "Doze"));
 
-        DozeMachine machine = new DozeMachine(
-                DozeSuspendScreenStatePreventingAdapter.wrapIfNeeded(
-                        DozeScreenStatePreventingAdapter.wrapIfNeeded(dozeService, params), params),
-                config,
-                wakeLock);
+        DozeMachine.Service wrappedService = DozeSuspendScreenStatePreventingAdapter.wrapIfNeeded(
+                DozeScreenStatePreventingAdapter.wrapIfNeeded(dozeService, params), params);
+        DozeMachine machine = new DozeMachine(wrappedService, config, wakeLock);
         machine.setParts(new DozeMachine.Part[]{
                 createDozeTriggers(context, sensorManager, host, config, params, handler, wakeLock,
                         machine),
                 createDozeUi(context, host, wakeLock, machine, handler, alarmManager),
+                createDozeScreenState(wrappedService),
+                createDozeScreenBrightness(context, wrappedService, sensorManager, handler),
         });
 
         return machine;
     }
 
+    private DozeMachine.Part createDozeScreenState(DozeMachine.Service service) {
+        return new DozeScreenState(service);
+    }
+
+    private DozeMachine.Part createDozeScreenBrightness(Context context,
+            DozeMachine.Service service, SensorManager sensorManager, Handler handler) {
+        Sensor sensor = DozeSensors.findSensorWithType(sensorManager,
+                context.getString(R.string.doze_brightness_sensor_type));
+        return new DozeScreenBrightness(context, service, sensorManager, sensor, handler);
+    }
+
     private DozeTriggers createDozeTriggers(Context context, SensorManager sensorManager,
             DozeHost host, AmbientDisplayConfiguration config, DozeParameters params,
             Handler handler, WakeLock wakeLock, DozeMachine machine) {
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
index 5526e6b..e72abf3 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -222,7 +222,6 @@
 
         updatePulseReason(newState, oldState, pulseReason);
         performTransitionOnComponents(oldState, newState);
-        updateScreenState(newState);
         updateWakeLockState(newState);
 
         resolveIntermediateState(newState);
@@ -307,13 +306,6 @@
         }
     }
 
-    private void updateScreenState(State newState) {
-        int state = newState.screenState();
-        if (state != Display.STATE_UNKNOWN) {
-            mDozeService.setDozeScreenState(state);
-        }
-    }
-
     private void resolveIntermediateState(State state) {
         switch (state) {
             case INITIALIZED:
@@ -360,5 +352,36 @@
 
         /** Request waking up. */
         void requestWakeUp();
+
+        /** Set screen brightness */
+        void setDozeScreenBrightness(int brightness);
+
+        class Delegate implements Service {
+            private final Service mDelegate;
+
+            public Delegate(Service delegate) {
+                mDelegate = delegate;
+            }
+
+            @Override
+            public void finish() {
+                mDelegate.finish();
+            }
+
+            @Override
+            public void setDozeScreenState(int state) {
+                mDelegate.setDozeScreenState(state);
+            }
+
+            @Override
+            public void requestWakeUp() {
+                mDelegate.requestWakeUp();
+            }
+
+            @Override
+            public void setDozeScreenBrightness(int brightness) {
+                mDelegate.setDozeScreenBrightness(brightness);
+            }
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
new file mode 100644
index 0000000..e461986
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2017 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.doze;
+
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.Handler;
+
+/**
+ * Controls the screen brightness when dozing.
+ */
+public class DozeScreenBrightness implements DozeMachine.Part, SensorEventListener {
+    private final Context mContext;
+    private final DozeMachine.Service mDozeService;
+    private final Handler mHandler;
+    private final SensorManager mSensorManager;
+    private final Sensor mLightSensor;
+    private boolean mRegistered;
+
+    public DozeScreenBrightness(Context context, DozeMachine.Service service,
+            SensorManager sensorManager, Sensor lightSensor, Handler handler) {
+        mContext = context;
+        mDozeService = service;
+        mSensorManager = sensorManager;
+        mLightSensor = lightSensor;
+        mHandler = handler;
+    }
+
+    @Override
+    public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
+        switch (newState) {
+            case INITIALIZED:
+                resetBrightnessToDefault();
+                break;
+            case DOZE_AOD:
+            case DOZE_REQUEST_PULSE:
+                setLightSensorEnabled(true);
+                break;
+            case DOZE:
+            case DOZE_AOD_PAUSED:
+                setLightSensorEnabled(false);
+                resetBrightnessToDefault();
+                break;
+            case FINISH:
+                setLightSensorEnabled(false);
+                break;
+        }
+    }
+
+    @Override
+    public void onSensorChanged(SensorEvent event) {
+        if (mRegistered) {
+            mDozeService.setDozeScreenBrightness(Math.max(1, (int) event.values[0]));
+        }
+    }
+
+    @Override
+    public void onAccuracyChanged(Sensor sensor, int accuracy) {
+    }
+
+    private void resetBrightnessToDefault() {
+        mDozeService.setDozeScreenBrightness(mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_screenBrightnessDoze));
+    }
+
+    private void setLightSensorEnabled(boolean enabled) {
+        if (enabled && !mRegistered && mLightSensor != null) {
+            mRegistered = mSensorManager.registerListener(this, mLightSensor,
+                    SensorManager.SENSOR_DELAY_NORMAL, mHandler);
+        } else if (!enabled && mRegistered) {
+            mSensorManager.unregisterListener(this);
+            mRegistered = false;
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
new file mode 100644
index 0000000..846ec27
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 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.doze;
+
+import android.content.Context;
+import android.view.Display;
+
+/**
+ * Controls the screen when dozing.
+ */
+public class DozeScreenState implements DozeMachine.Part {
+    private final DozeMachine.Service mDozeService;
+
+    public DozeScreenState(DozeMachine.Service service) {
+        mDozeService = service;
+    }
+
+    @Override
+    public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
+        int screenState = newState.screenState();
+        if (screenState != Display.STATE_UNKNOWN) {
+            mDozeService.setDozeScreenState(screenState);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java
index ad5897a..5d0a9d7 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java
@@ -24,18 +24,11 @@
 /**
  * Prevents usage of doze screen states on devices that don't support them.
  */
-public class DozeScreenStatePreventingAdapter implements DozeMachine.Service {
-
-    private final DozeMachine.Service mInner;
+public class DozeScreenStatePreventingAdapter extends DozeMachine.Service.Delegate {
 
     @VisibleForTesting
     DozeScreenStatePreventingAdapter(DozeMachine.Service inner) {
-        mInner = inner;
-    }
-
-    @Override
-    public void finish() {
-        mInner.finish();
+        super(inner);
     }
 
     @Override
@@ -43,12 +36,7 @@
         if (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND) {
             state = Display.STATE_ON;
         }
-        mInner.setDozeScreenState(state);
-    }
-
-    @Override
-    public void requestWakeUp() {
-        mInner.requestWakeUp();
+        super.setDozeScreenState(state);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 23da716..b0b77c6 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -100,10 +100,14 @@
     }
 
     private Sensor findSensorWithType(String type) {
+        return findSensorWithType(mSensorManager, type);
+    }
+
+    static Sensor findSensorWithType(SensorManager sensorManager, String type) {
         if (TextUtils.isEmpty(type)) {
             return null;
         }
-        List<Sensor> sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
+        List<Sensor> sensorList = sensorManager.getSensorList(Sensor.TYPE_ALL);
         for (Sensor s : sensorList) {
             if (type.equals(s.getStringType())) {
                 return s;
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index d9fb087..98b1106 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -76,8 +76,6 @@
         super.onDreamingStarted();
         mDozeMachine.requestState(DozeMachine.State.INITIALIZED);
         startDozing();
-        setDozeScreenBrightness(getResources().getInteger(
-                com.android.internal.R.integer.config_screenBrightnessDoze));
         if (mDozePlugin != null) {
             mDozePlugin.onDreamingStarted();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapter.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapter.java
index 1e06797..1c6521f 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapter.java
@@ -24,18 +24,11 @@
 /**
  * Prevents usage of doze screen states on devices that don't support them.
  */
-public class DozeSuspendScreenStatePreventingAdapter implements DozeMachine.Service {
-
-    private final DozeMachine.Service mInner;
+public class DozeSuspendScreenStatePreventingAdapter extends DozeMachine.Service.Delegate {
 
     @VisibleForTesting
     DozeSuspendScreenStatePreventingAdapter(DozeMachine.Service inner) {
-        mInner = inner;
-    }
-
-    @Override
-    public void finish() {
-        mInner.finish();
+        super(inner);
     }
 
     @Override
@@ -43,12 +36,7 @@
         if (state == Display.STATE_DOZE_SUSPEND) {
             state = Display.STATE_DOZE;
         }
-        mInner.setDozeScreenState(state);
-    }
-
-    @Override
-    public void requestWakeUp() {
-        mInner.requestWakeUp();
+        super.setDozeScreenState(state);
     }
 
     /**