1 /* 2 * Copyright (C) 2024 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.server.display.brightness.clamper; 18 19 import android.annotation.Nullable; 20 import android.content.res.Resources; 21 import android.hardware.Sensor; 22 import android.hardware.SensorEvent; 23 import android.hardware.SensorEventListener; 24 import android.hardware.SensorManager; 25 import android.os.Handler; 26 import android.os.SystemClock; 27 import android.util.Slog; 28 import android.view.Display; 29 30 import com.android.internal.R; 31 import com.android.internal.annotations.VisibleForTesting; 32 import com.android.server.display.config.SensorData; 33 import com.android.server.display.utils.AmbientFilter; 34 import com.android.server.display.utils.AmbientFilterFactory; 35 import com.android.server.display.utils.DebugUtils; 36 import com.android.server.display.utils.SensorUtils; 37 38 import java.io.PrintWriter; 39 import java.util.concurrent.TimeUnit; 40 41 /** 42 * Manages light sensor subscription and notifies its listener about ambient lux changes 43 */ 44 public class LightSensorController { 45 private static final String TAG = "LightSensorController"; 46 47 // To enable these logs, run: 48 // 'adb shell setprop persist.log.tag.LightSensorController DEBUG && adb reboot' 49 private static final boolean DEBUG = DebugUtils.isDebuggable(TAG); 50 static final float INVALID_LUX = -1f; 51 52 private final SensorManager mSensorManager; 53 private final LightSensorListener mLightSensorListener; 54 private final Handler mHandler; 55 private final Injector mInjector; 56 private final AmbientFilter mAmbientFilter; 57 58 private Sensor mLightSensor; 59 private Sensor mRegisteredLightSensor = null; 60 private final int mLightSensorRate; 61 62 private final SensorEventListener mLightSensorEventListener = new SensorEventListener() { 63 @Override 64 public void onSensorChanged(SensorEvent event) { 65 if (event.sensor != mRegisteredLightSensor) { 66 return; 67 } 68 long now = mInjector.getTime(); 69 mAmbientFilter.addValue(TimeUnit.NANOSECONDS.toMillis(event.timestamp), 70 event.values[0]); 71 final float lux = mAmbientFilter.getEstimate(now); 72 mLightSensorListener.onAmbientLuxChange(lux); 73 } 74 75 @Override 76 public void onAccuracyChanged(Sensor sensor, int accuracy) { 77 // unused 78 } 79 }; 80 LightSensorController(SensorManager sensorManager, Resources resources, LightSensorListener listener, Handler handler)81 LightSensorController(SensorManager sensorManager, Resources resources, 82 LightSensorListener listener, Handler handler) { 83 this(sensorManager, resources, listener, handler, new Injector()); 84 } 85 86 @VisibleForTesting LightSensorController(SensorManager sensorManager, Resources resources, LightSensorListener listener, Handler handler, Injector injector)87 LightSensorController(SensorManager sensorManager, Resources resources, 88 LightSensorListener listener, Handler handler, Injector injector) { 89 mSensorManager = sensorManager; 90 mLightSensorRate = injector.getLightSensorRate(resources); 91 mAmbientFilter = injector.getAmbientFilter(resources); 92 mLightSensorListener = listener; 93 mHandler = handler; 94 mInjector = injector; 95 } 96 restart()97 void restart() { 98 if (mRegisteredLightSensor == mLightSensor) { 99 return; 100 } 101 if (mLightSensor != null) { 102 mSensorManager.registerListener(mLightSensorEventListener, 103 mLightSensor, mLightSensorRate * 1000, mHandler); 104 } 105 if (mRegisteredLightSensor != null) { 106 stop(); 107 } 108 mRegisteredLightSensor = mLightSensor; 109 110 if (DEBUG) { 111 Slog.d(TAG, "restart"); 112 } 113 } 114 stop()115 void stop() { 116 if (mRegisteredLightSensor == null) { 117 return; 118 } 119 mSensorManager.unregisterListener(mLightSensorEventListener, mRegisteredLightSensor); 120 mRegisteredLightSensor = null; 121 mAmbientFilter.clear(); 122 mLightSensorListener.onAmbientLuxChange(INVALID_LUX); 123 if (DEBUG) { 124 Slog.d(TAG, "stop"); 125 } 126 } 127 configure(SensorData sensorData, int displayId)128 void configure(SensorData sensorData, int displayId) { 129 final int fallbackType = displayId == Display.DEFAULT_DISPLAY 130 ? Sensor.TYPE_LIGHT : SensorUtils.NO_FALLBACK; 131 mLightSensor = mInjector.getLightSensor(mSensorManager, sensorData, fallbackType); 132 } 133 dump(PrintWriter writer)134 void dump(PrintWriter writer) { 135 writer.println("LightSensorController"); 136 writer.println(" mLightSensor=" + mLightSensor); 137 writer.println(" mRegisteredLightSensor=" + mRegisteredLightSensor); 138 } 139 140 static class Injector { 141 @Nullable getLightSensor(SensorManager sensorManager, SensorData sensorData, int fallbackType)142 Sensor getLightSensor(SensorManager sensorManager, SensorData sensorData, 143 int fallbackType) { 144 return SensorUtils.findSensor(sensorManager, sensorData, fallbackType); 145 } 146 getAmbientFilter(Resources resources)147 AmbientFilter getAmbientFilter(Resources resources) { 148 return AmbientFilterFactory.createBrightnessFilter(TAG, resources); 149 } 150 getLightSensorRate(Resources resources)151 int getLightSensorRate(Resources resources) { 152 return resources.getInteger(R.integer.config_autoBrightnessLightSensorRate); 153 } 154 155 // should be consistent with SensorEvent.timestamp getTime()156 long getTime() { 157 return SystemClock.elapsedRealtime(); 158 } 159 } 160 161 interface LightSensorListener { onAmbientLuxChange(float ambientLux)162 void onAmbientLuxChange(float ambientLux); 163 } 164 } 165