blob: 42defac5bab8e1a4cfb70eda835338f8fb6fcc2a [file] [log] [blame]
/*
* Copyright (C) 2022 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.server.display;
import android.annotation.Nullable;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Handler;
import android.os.PowerManager;
import android.util.IndentingPrintWriter;
import com.android.internal.annotations.VisibleForTesting;
import java.io.PrintWriter;
/**
* Controls the light sensor when the screen is off. The sensor used here does not report lux values
* but an index that needs to be mapped to a lux value.
*/
public class ScreenOffBrightnessSensorController implements SensorEventListener {
private static final String TAG = "ScreenOffBrightnessSensorController";
private static final int SENSOR_INVALID_VALUE = -1;
private static final long SENSOR_VALUE_VALID_TIME_MILLIS = 1500;
private final Handler mHandler;
private final Clock mClock;
private final SensorManager mSensorManager;
private final Sensor mLightSensor;
private final int[] mSensorValueToLux;
private boolean mRegistered;
private int mLastSensorValue = SENSOR_INVALID_VALUE;
private long mSensorDisableTime = -1;
// The mapper to translate ambient lux to screen brightness in the range [0, 1.0].
@Nullable
private final BrightnessMappingStrategy mBrightnessMapper;
public ScreenOffBrightnessSensorController(
SensorManager sensorManager,
Sensor lightSensor,
Handler handler,
Clock clock,
int[] sensorValueToLux,
BrightnessMappingStrategy brightnessMapper) {
mSensorManager = sensorManager;
mLightSensor = lightSensor;
mHandler = handler;
mClock = clock;
mSensorValueToLux = sensorValueToLux;
mBrightnessMapper = brightnessMapper;
}
@Override
public void onSensorChanged(SensorEvent event) {
if (mRegistered) {
mLastSensorValue = (int) event.values[0];
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
void setLightSensorEnabled(boolean enabled) {
if (enabled && !mRegistered) {
// Wait until we get an event from the sensor indicating ready.
mRegistered = mSensorManager.registerListener(this, mLightSensor,
SensorManager.SENSOR_DELAY_NORMAL, mHandler);
mLastSensorValue = SENSOR_INVALID_VALUE;
} else if (!enabled && mRegistered) {
mSensorManager.unregisterListener(this);
mRegistered = false;
mSensorDisableTime = mClock.uptimeMillis();
}
}
void stop() {
setLightSensorEnabled(false);
}
float getAutomaticScreenBrightness() {
if (mLastSensorValue < 0 || mLastSensorValue >= mSensorValueToLux.length
|| (!mRegistered
&& mClock.uptimeMillis() - mSensorDisableTime > SENSOR_VALUE_VALID_TIME_MILLIS)) {
return PowerManager.BRIGHTNESS_INVALID_FLOAT;
}
int lux = mSensorValueToLux[mLastSensorValue];
if (lux < 0) {
return PowerManager.BRIGHTNESS_INVALID_FLOAT;
}
return mBrightnessMapper.getBrightness(lux);
}
/** Dump current state */
public void dump(PrintWriter pw) {
pw.println("Screen Off Brightness Sensor Controller:");
IndentingPrintWriter idpw = new IndentingPrintWriter(pw);
idpw.increaseIndent();
idpw.println("registered=" + mRegistered);
idpw.println("lastSensorValue=" + mLastSensorValue);
}
/** Functional interface for providing time. */
@VisibleForTesting
interface Clock {
/**
* Returns current time in milliseconds since boot, not counting time spent in deep sleep.
*/
long uptimeMillis();
}
}