• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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