Home | History | Annotate | Download | only in doze
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.systemui.doze;
     18 
     19 import android.content.Context;
     20 import android.hardware.Sensor;
     21 import android.hardware.SensorEvent;
     22 import android.hardware.SensorEventListener;
     23 import android.hardware.SensorManager;
     24 import android.os.Handler;
     25 import android.os.Trace;
     26 
     27 import com.android.internal.annotations.VisibleForTesting;
     28 
     29 /**
     30  * Controls the screen brightness when dozing.
     31  */
     32 public class DozeScreenBrightness implements DozeMachine.Part, SensorEventListener {
     33     private final Context mContext;
     34     private final DozeMachine.Service mDozeService;
     35     private final DozeHost mDozeHost;
     36     private final Handler mHandler;
     37     private final SensorManager mSensorManager;
     38     private final Sensor mLightSensor;
     39     private final int[] mSensorToBrightness;
     40     private final int[] mSensorToScrimOpacity;
     41 
     42     private boolean mRegistered;
     43     private int mDefaultDozeBrightness;
     44     private boolean mPaused = false;
     45     private int mLastSensorValue = -1;
     46 
     47     public DozeScreenBrightness(Context context, DozeMachine.Service service,
     48             SensorManager sensorManager, Sensor lightSensor, DozeHost host,
     49             Handler handler, int defaultDozeBrightness, int[] sensorToBrightness,
     50             int[] sensorToScrimOpacity) {
     51         mContext = context;
     52         mDozeService = service;
     53         mSensorManager = sensorManager;
     54         mLightSensor = lightSensor;
     55         mDozeHost = host;
     56         mHandler = handler;
     57 
     58         mDefaultDozeBrightness = defaultDozeBrightness;
     59         mSensorToBrightness = sensorToBrightness;
     60         mSensorToScrimOpacity = sensorToScrimOpacity;
     61     }
     62 
     63     @VisibleForTesting
     64     public DozeScreenBrightness(Context context, DozeMachine.Service service,
     65             SensorManager sensorManager, Sensor lightSensor, DozeHost host,
     66             Handler handler, AlwaysOnDisplayPolicy policy) {
     67         this(context, service, sensorManager, lightSensor, host, handler,
     68                 context.getResources().getInteger(
     69                         com.android.internal.R.integer.config_screenBrightnessDoze),
     70                 policy.screenBrightnessArray, policy.dimmingScrimArray);
     71     }
     72 
     73     @Override
     74     public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
     75         switch (newState) {
     76             case INITIALIZED:
     77                 resetBrightnessToDefault();
     78                 break;
     79             case DOZE_AOD:
     80             case DOZE_REQUEST_PULSE:
     81                 setLightSensorEnabled(true);
     82                 break;
     83             case DOZE:
     84                 setLightSensorEnabled(false);
     85                 resetBrightnessToDefault();
     86                 break;
     87             case FINISH:
     88                 setLightSensorEnabled(false);
     89                 break;
     90         }
     91         if (newState != DozeMachine.State.FINISH) {
     92             setPaused(newState == DozeMachine.State.DOZE_AOD_PAUSED);
     93         }
     94     }
     95 
     96     @Override
     97     public void onSensorChanged(SensorEvent event) {
     98         Trace.beginSection("DozeScreenBrightness.onSensorChanged" + event.values[0]);
     99         try {
    100             if (mRegistered) {
    101                 mLastSensorValue = (int) event.values[0];
    102                 updateBrightnessAndReady();
    103             }
    104         } finally {
    105             Trace.endSection();
    106         }
    107     }
    108 
    109     private void updateBrightnessAndReady() {
    110         if (mRegistered) {
    111             int brightness = computeBrightness(mLastSensorValue);
    112             boolean brightnessReady = brightness > 0;
    113             if (brightnessReady) {
    114                 mDozeService.setDozeScreenBrightness(brightness);
    115             }
    116 
    117             int scrimOpacity = -1;
    118             if (mPaused) {
    119                 // If AOD is paused, force the screen black until the
    120                 // sensor reports a new brightness. This ensures that when the screen comes on
    121                 // again, it will only show after the brightness sensor has stabilized,
    122                 // avoiding a potential flicker.
    123                 scrimOpacity = 255;
    124             } else if (brightnessReady) {
    125                 // Only unblank scrim once brightness is ready.
    126                 scrimOpacity = computeScrimOpacity(mLastSensorValue);
    127             }
    128             if (scrimOpacity >= 0) {
    129                 mDozeHost.setAodDimmingScrim(scrimOpacity / 255f);
    130             }
    131         }
    132     }
    133 
    134     private int computeScrimOpacity(int sensorValue) {
    135         if (sensorValue < 0 || sensorValue >= mSensorToScrimOpacity.length) {
    136             return -1;
    137         }
    138         return mSensorToScrimOpacity[sensorValue];
    139     }
    140 
    141     private int computeBrightness(int sensorValue) {
    142         if (sensorValue < 0 || sensorValue >= mSensorToBrightness.length) {
    143             return -1;
    144         }
    145         return mSensorToBrightness[sensorValue];
    146     }
    147 
    148     @Override
    149     public void onAccuracyChanged(Sensor sensor, int accuracy) {
    150     }
    151 
    152     private void resetBrightnessToDefault() {
    153         mDozeService.setDozeScreenBrightness(mDefaultDozeBrightness);
    154         mDozeHost.setAodDimmingScrim(0f);
    155     }
    156 
    157     private void setLightSensorEnabled(boolean enabled) {
    158         if (enabled && !mRegistered && mLightSensor != null) {
    159             // Wait until we get an event from the sensor until indicating ready.
    160             mRegistered = mSensorManager.registerListener(this, mLightSensor,
    161                     SensorManager.SENSOR_DELAY_NORMAL, mHandler);
    162             mLastSensorValue = -1;
    163         } else if (!enabled && mRegistered) {
    164             mSensorManager.unregisterListener(this);
    165             mRegistered = false;
    166             mLastSensorValue = -1;
    167             // Sensor is not enabled, hence we use the default brightness and are always ready.
    168         }
    169     }
    170 
    171     private void setPaused(boolean paused) {
    172         if (mPaused != paused) {
    173             mPaused = paused;
    174             updateBrightnessAndReady();
    175         }
    176     }
    177 
    178 }
    179