Reload the Ambient Light Sensor on Display Change
This change fixes the multi display scenario - when the underlying display device changes, we should reload the appropriate ambient light sensor for the default display. Bug: 198125195 Test: adb shell dumpsys sensorservice Test: atest com.android.server.display Change-Id: I8b2d76d916d79f7dae22d81adc3ce69780bf9bfc
This commit is contained in:
@@ -2630,6 +2630,9 @@ public class DisplayDeviceConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uniquely identifies a Sensor, with the combination of Type and Name.
|
||||||
|
*/
|
||||||
static class SensorData {
|
static class SensorData {
|
||||||
public String type;
|
public String type;
|
||||||
public String name;
|
public String name;
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ import android.provider.DeviceConfig;
|
|||||||
import android.provider.DeviceConfigInterface;
|
import android.provider.DeviceConfigInterface;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.sysprop.SurfaceFlingerProperties;
|
import android.sysprop.SurfaceFlingerProperties;
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.util.IndentingPrintWriter;
|
import android.util.IndentingPrintWriter;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
@@ -70,6 +69,7 @@ import com.android.internal.os.BackgroundThread;
|
|||||||
import com.android.server.LocalServices;
|
import com.android.server.LocalServices;
|
||||||
import com.android.server.display.utils.AmbientFilter;
|
import com.android.server.display.utils.AmbientFilter;
|
||||||
import com.android.server.display.utils.AmbientFilterFactory;
|
import com.android.server.display.utils.AmbientFilterFactory;
|
||||||
|
import com.android.server.display.utils.SensorUtils;
|
||||||
import com.android.server.sensors.SensorManagerInternal;
|
import com.android.server.sensors.SensorManagerInternal;
|
||||||
import com.android.server.sensors.SensorManagerInternal.ProximityActiveListener;
|
import com.android.server.sensors.SensorManagerInternal.ProximityActiveListener;
|
||||||
import com.android.server.statusbar.StatusBarManagerInternal;
|
import com.android.server.statusbar.StatusBarManagerInternal;
|
||||||
@@ -683,14 +683,20 @@ public class DisplayModeDirector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A utility to make this class aware of the new display configs whenever the default display is
|
* Called when the underlying display device of the default display is changed.
|
||||||
* changed
|
* Some data in this class relates to the physical display of the device, and so we need to
|
||||||
|
* reload the configurations based on this.
|
||||||
|
* E.g. the brightness sensors and refresh rate capabilities depend on the physical display
|
||||||
|
* device that is being used, so will be reloaded.
|
||||||
|
*
|
||||||
|
* @param displayDeviceConfig configurations relating to the underlying display device.
|
||||||
*/
|
*/
|
||||||
public void defaultDisplayDeviceUpdated(DisplayDeviceConfig displayDeviceConfig) {
|
public void defaultDisplayDeviceUpdated(DisplayDeviceConfig displayDeviceConfig) {
|
||||||
mSettingsObserver.setRefreshRates(displayDeviceConfig,
|
mSettingsObserver.setRefreshRates(displayDeviceConfig,
|
||||||
/* attemptLoadingFromDeviceConfig= */ true);
|
/* attemptLoadingFromDeviceConfig= */ true);
|
||||||
mBrightnessObserver.updateBlockingZoneThresholds(displayDeviceConfig,
|
mBrightnessObserver.updateBlockingZoneThresholds(displayDeviceConfig,
|
||||||
/* attemptLoadingFromDeviceConfig= */ true);
|
/* attemptLoadingFromDeviceConfig= */ true);
|
||||||
|
mBrightnessObserver.reloadLightSensor(displayDeviceConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1739,6 +1745,9 @@ public class DisplayModeDirector {
|
|||||||
|
|
||||||
private SensorManager mSensorManager;
|
private SensorManager mSensorManager;
|
||||||
private Sensor mLightSensor;
|
private Sensor mLightSensor;
|
||||||
|
private Sensor mRegisteredLightSensor;
|
||||||
|
private String mLightSensorType;
|
||||||
|
private String mLightSensorName;
|
||||||
private final LightSensorEventListener mLightSensorListener =
|
private final LightSensorEventListener mLightSensorListener =
|
||||||
new LightSensorEventListener();
|
new LightSensorEventListener();
|
||||||
// Take it as low brightness before valid sensor data comes
|
// Take it as low brightness before valid sensor data comes
|
||||||
@@ -1899,17 +1908,8 @@ public class DisplayModeDirector {
|
|||||||
return mLowAmbientBrightnessThresholds;
|
return mLowAmbientBrightnessThresholds;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerLightSensor(SensorManager sensorManager, Sensor lightSensor) {
|
|
||||||
mSensorManager = sensorManager;
|
|
||||||
mLightSensor = lightSensor;
|
|
||||||
|
|
||||||
mSensorManager.registerListener(mLightSensorListener,
|
|
||||||
mLightSensor, LIGHT_SENSOR_RATE_MS * 1000, mHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void observe(SensorManager sensorManager) {
|
public void observe(SensorManager sensorManager) {
|
||||||
mSensorManager = sensorManager;
|
mSensorManager = sensorManager;
|
||||||
final ContentResolver cr = mContext.getContentResolver();
|
|
||||||
mBrightness = getBrightness(Display.DEFAULT_DISPLAY);
|
mBrightness = getBrightness(Display.DEFAULT_DISPLAY);
|
||||||
|
|
||||||
// DeviceConfig is accessible after system ready.
|
// DeviceConfig is accessible after system ready.
|
||||||
@@ -2053,6 +2053,10 @@ public class DisplayModeDirector {
|
|||||||
pw.println(" mAmbientHighBrightnessThresholds: " + d);
|
pw.println(" mAmbientHighBrightnessThresholds: " + d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pw.println(" mRegisteredLightSensor: " + mRegisteredLightSensor);
|
||||||
|
pw.println(" mLightSensor: " + mLightSensor);
|
||||||
|
pw.println(" mLightSensorName: " + mLightSensorName);
|
||||||
|
pw.println(" mLightSensorType: " + mLightSensorType);
|
||||||
mLightSensorListener.dumpLocked(pw);
|
mLightSensorListener.dumpLocked(pw);
|
||||||
|
|
||||||
if (mAmbientFilter != null) {
|
if (mAmbientFilter != null) {
|
||||||
@@ -2106,27 +2110,9 @@ public class DisplayModeDirector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mShouldObserveAmbientLowChange || mShouldObserveAmbientHighChange) {
|
if (mShouldObserveAmbientLowChange || mShouldObserveAmbientHighChange) {
|
||||||
Resources resources = mContext.getResources();
|
Sensor lightSensor = getLightSensor();
|
||||||
String lightSensorType = resources.getString(
|
|
||||||
com.android.internal.R.string.config_displayLightSensorType);
|
|
||||||
|
|
||||||
Sensor lightSensor = null;
|
if (lightSensor != null && lightSensor != mLightSensor) {
|
||||||
if (!TextUtils.isEmpty(lightSensorType)) {
|
|
||||||
List<Sensor> sensors = mSensorManager.getSensorList(Sensor.TYPE_ALL);
|
|
||||||
for (int i = 0; i < sensors.size(); i++) {
|
|
||||||
Sensor sensor = sensors.get(i);
|
|
||||||
if (lightSensorType.equals(sensor.getStringType())) {
|
|
||||||
lightSensor = sensor;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lightSensor == null) {
|
|
||||||
lightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lightSensor != null) {
|
|
||||||
final Resources res = mContext.getResources();
|
final Resources res = mContext.getResources();
|
||||||
|
|
||||||
mAmbientFilter = AmbientFilterFactory.createBrightnessFilter(TAG, res);
|
mAmbientFilter = AmbientFilterFactory.createBrightnessFilter(TAG, res);
|
||||||
@@ -2137,14 +2123,40 @@ public class DisplayModeDirector {
|
|||||||
mLightSensor = null;
|
mLightSensor = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mRefreshRateChangeable) {
|
|
||||||
updateSensorStatus();
|
updateSensorStatus();
|
||||||
|
if (mRefreshRateChangeable) {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
onBrightnessChangedLocked();
|
onBrightnessChangedLocked();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void reloadLightSensor(DisplayDeviceConfig displayDeviceConfig) {
|
||||||
|
reloadLightSensorData(displayDeviceConfig);
|
||||||
|
restartObserver();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reloadLightSensorData(DisplayDeviceConfig displayDeviceConfig) {
|
||||||
|
// The displayDeviceConfig (ddc) contains display specific preferences. When loaded,
|
||||||
|
// it naturally falls back to the global config.xml.
|
||||||
|
if (displayDeviceConfig != null
|
||||||
|
&& displayDeviceConfig.getAmbientLightSensor() != null) {
|
||||||
|
// This covers both the ddc and the config.xml fallback
|
||||||
|
mLightSensorType = displayDeviceConfig.getAmbientLightSensor().type;
|
||||||
|
mLightSensorName = displayDeviceConfig.getAmbientLightSensor().name;
|
||||||
|
} else if (mLightSensorName == null && mLightSensorType == null) {
|
||||||
|
Resources resources = mContext.getResources();
|
||||||
|
mLightSensorType = resources.getString(
|
||||||
|
com.android.internal.R.string.config_displayLightSensorType);
|
||||||
|
mLightSensorName = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Sensor getLightSensor() {
|
||||||
|
return SensorUtils.findSensor(mSensorManager, mLightSensorType,
|
||||||
|
mLightSensorName, Sensor.TYPE_LIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks to see if at least one value is positive, in which case it is necessary to listen
|
* Checks to see if at least one value is positive, in which case it is necessary to listen
|
||||||
* to value changes.
|
* to value changes.
|
||||||
@@ -2288,19 +2300,38 @@ public class DisplayModeDirector {
|
|||||||
|
|
||||||
if ((mShouldObserveAmbientLowChange || mShouldObserveAmbientHighChange)
|
if ((mShouldObserveAmbientLowChange || mShouldObserveAmbientHighChange)
|
||||||
&& isDeviceActive() && !mLowPowerModeEnabled && mRefreshRateChangeable) {
|
&& isDeviceActive() && !mLowPowerModeEnabled && mRefreshRateChangeable) {
|
||||||
|
registerLightSensor();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
unregisterSensorListener();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerLightSensor() {
|
||||||
|
if (mRegisteredLightSensor == mLightSensor) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mRegisteredLightSensor != null) {
|
||||||
|
unregisterSensorListener();
|
||||||
|
}
|
||||||
|
|
||||||
mSensorManager.registerListener(mLightSensorListener,
|
mSensorManager.registerListener(mLightSensorListener,
|
||||||
mLightSensor, LIGHT_SENSOR_RATE_MS * 1000, mHandler);
|
mLightSensor, LIGHT_SENSOR_RATE_MS * 1000, mHandler);
|
||||||
|
mRegisteredLightSensor = mLightSensor;
|
||||||
if (mLoggingEnabled) {
|
if (mLoggingEnabled) {
|
||||||
Slog.d(TAG, "updateSensorStatus: registerListener");
|
Slog.d(TAG, "updateSensorStatus: registerListener");
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
private void unregisterSensorListener() {
|
||||||
mLightSensorListener.removeCallbacks();
|
mLightSensorListener.removeCallbacks();
|
||||||
mSensorManager.unregisterListener(mLightSensorListener);
|
mSensorManager.unregisterListener(mLightSensorListener);
|
||||||
|
mRegisteredLightSensor = null;
|
||||||
if (mLoggingEnabled) {
|
if (mLoggingEnabled) {
|
||||||
Slog.d(TAG, "updateSensorStatus: unregisterListener");
|
Slog.d(TAG, "updateSensorStatus: unregisterListener");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isDeviceActive() {
|
private boolean isDeviceActive() {
|
||||||
return mDefaultDisplayState == Display.STATE_ON;
|
return mDefaultDisplayState == Display.STATE_ON;
|
||||||
|
|||||||
@@ -33,6 +33,10 @@ public class SensorUtils {
|
|||||||
*/
|
*/
|
||||||
public static Sensor findSensor(SensorManager sensorManager, String sensorType,
|
public static Sensor findSensor(SensorManager sensorManager, String sensorType,
|
||||||
String sensorName, int fallbackType) {
|
String sensorName, int fallbackType) {
|
||||||
|
if (sensorManager == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if ("".equals(sensorName) && "".equals(sensorType)) {
|
if ("".equals(sensorName) && "".equals(sensorType)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import static org.junit.Assert.assertTrue;
|
|||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.any;
|
import static org.mockito.Mockito.any;
|
||||||
|
import static org.mockito.Mockito.doAnswer;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
@@ -73,6 +74,7 @@ import android.provider.Settings;
|
|||||||
import android.test.mock.MockContentResolver;
|
import android.test.mock.MockContentResolver;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
|
import android.util.TypedValue;
|
||||||
import android.view.Display;
|
import android.view.Display;
|
||||||
import android.view.SurfaceControl.RefreshRateRange;
|
import android.view.SurfaceControl.RefreshRateRange;
|
||||||
import android.view.SurfaceControl.RefreshRateRanges;
|
import android.view.SurfaceControl.RefreshRateRanges;
|
||||||
@@ -102,6 +104,7 @@ import org.mockito.ArgumentCaptor;
|
|||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
|
import org.mockito.stubbing.Answer;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -2293,6 +2296,61 @@ public class DisplayModeDirectorTest {
|
|||||||
new int[]{20});
|
new int[]{20});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSensorReloadOnDeviceSwitch() throws Exception {
|
||||||
|
// First, configure brightness zones or DMD won't register for sensor data.
|
||||||
|
final FakeDeviceConfig config = mInjector.getDeviceConfig();
|
||||||
|
config.setRefreshRateInHighZone(60);
|
||||||
|
config.setHighDisplayBrightnessThresholds(new int[] { 255 });
|
||||||
|
config.setHighAmbientBrightnessThresholds(new int[] { 8000 });
|
||||||
|
|
||||||
|
DisplayModeDirector director =
|
||||||
|
createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0);
|
||||||
|
setPeakRefreshRate(90 /*fps*/);
|
||||||
|
director.getSettingsObserver().setDefaultRefreshRate(90);
|
||||||
|
director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON);
|
||||||
|
|
||||||
|
Sensor lightSensorOne = TestUtils.createSensor(Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT);
|
||||||
|
Sensor lightSensorTwo = TestUtils.createSensor(Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT);
|
||||||
|
SensorManager sensorManager = createMockSensorManager(lightSensorOne, lightSensorTwo);
|
||||||
|
when(sensorManager.getDefaultSensor(5)).thenReturn(lightSensorOne, lightSensorTwo);
|
||||||
|
director.start(sensorManager);
|
||||||
|
ArgumentCaptor<SensorEventListener> listenerCaptor =
|
||||||
|
ArgumentCaptor.forClass(SensorEventListener.class);
|
||||||
|
verify(sensorManager, Mockito.timeout(TimeUnit.SECONDS.toMillis(1)))
|
||||||
|
.registerListener(
|
||||||
|
listenerCaptor.capture(),
|
||||||
|
eq(lightSensorOne),
|
||||||
|
anyInt(),
|
||||||
|
any(Handler.class));
|
||||||
|
|
||||||
|
DisplayDeviceConfig ddcMock = mock(DisplayDeviceConfig.class);
|
||||||
|
when(ddcMock.getDefaultLowRefreshRate()).thenReturn(50);
|
||||||
|
when(ddcMock.getDefaultHighRefreshRate()).thenReturn(55);
|
||||||
|
when(ddcMock.getLowDisplayBrightnessThresholds()).thenReturn(new int[]{25});
|
||||||
|
when(ddcMock.getLowAmbientBrightnessThresholds()).thenReturn(new int[]{30});
|
||||||
|
when(ddcMock.getHighDisplayBrightnessThresholds()).thenReturn(new int[]{210});
|
||||||
|
when(ddcMock.getHighAmbientBrightnessThresholds()).thenReturn(new int[]{2100});
|
||||||
|
|
||||||
|
Resources resMock = mock(Resources.class);
|
||||||
|
when(resMock.getInteger(
|
||||||
|
com.android.internal.R.integer.config_displayWhiteBalanceBrightnessFilterHorizon))
|
||||||
|
.thenReturn(3);
|
||||||
|
ArgumentCaptor<TypedValue> valueArgumentCaptor = ArgumentCaptor.forClass(TypedValue.class);
|
||||||
|
doAnswer((Answer<Void>) invocation -> {
|
||||||
|
valueArgumentCaptor.getValue().type = 4;
|
||||||
|
valueArgumentCaptor.getValue().data = 13;
|
||||||
|
return null;
|
||||||
|
}).when(resMock).getValue(anyInt(), valueArgumentCaptor.capture(), eq(true));
|
||||||
|
when(mContext.getResources()).thenReturn(resMock);
|
||||||
|
|
||||||
|
director.defaultDisplayDeviceUpdated(ddcMock);
|
||||||
|
|
||||||
|
verify(sensorManager).unregisterListener(any(SensorEventListener.class));
|
||||||
|
verify(sensorManager).registerListener(any(SensorEventListener.class),
|
||||||
|
eq(lightSensorTwo), anyInt(), any(Handler.class));
|
||||||
|
}
|
||||||
|
|
||||||
private Temperature getSkinTemp(@Temperature.ThrottlingStatus int status) {
|
private Temperature getSkinTemp(@Temperature.ThrottlingStatus int status) {
|
||||||
return new Temperature(30.0f, Temperature.TYPE_SKIN, "test_skin_temp", status);
|
return new Temperature(30.0f, Temperature.TYPE_SKIN, "test_skin_temp", status);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user