• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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;
18 
19 import android.annotation.NonNull;
20 import android.os.Handler;
21 import android.os.Looper;
22 import android.os.Message;
23 import android.util.Slog;
24 
25 import com.android.internal.annotations.GuardedBy;
26 
27 import java.util.concurrent.CopyOnWriteArraySet;
28 
29 /**
30  * Saves brightness to a persistent data store, enabling each logical display to have its own
31  * brightness.
32  */
33 public class BrightnessSetting {
34     private static final String TAG = "BrightnessSetting";
35 
36     private static final int MSG_BRIGHTNESS_CHANGED = 1;
37 
38     private final PersistentDataStore mPersistentDataStore;
39     private final DisplayManagerService.SyncRoot mSyncRoot;
40 
41     private final LogicalDisplay mLogicalDisplay;
42 
43     private final Handler mHandler = new Handler(Looper.getMainLooper()) {
44         @Override
45         public void handleMessage(Message msg) {
46             if (msg.what == MSG_BRIGHTNESS_CHANGED) {
47                 float brightnessVal = Float.intBitsToFloat(msg.arg1);
48                 notifyListeners(brightnessVal);
49             }
50         }
51     };
52 
53     private final CopyOnWriteArraySet<BrightnessSettingListener> mListeners =
54             new CopyOnWriteArraySet<>();
55 
56     @GuardedBy("mSyncRoot")
57     private float mBrightness;
58 
BrightnessSetting(@onNull PersistentDataStore persistentDataStore, @NonNull LogicalDisplay logicalDisplay, DisplayManagerService.SyncRoot syncRoot)59     BrightnessSetting(@NonNull PersistentDataStore persistentDataStore,
60             @NonNull LogicalDisplay logicalDisplay,
61             DisplayManagerService.SyncRoot syncRoot) {
62         mPersistentDataStore = persistentDataStore;
63         mLogicalDisplay = logicalDisplay;
64         mBrightness = mPersistentDataStore.getBrightness(
65                 mLogicalDisplay.getPrimaryDisplayDeviceLocked());
66         mSyncRoot = syncRoot;
67     }
68 
69     /**
70      * Returns the brightness from the brightness setting
71      *
72      * @return brightness for the current display
73      */
getBrightness()74     public float getBrightness() {
75         synchronized (mSyncRoot) {
76             return mBrightness;
77         }
78     }
79 
80     /**
81      * Registers listener for brightness setting change events.
82      */
registerListener(BrightnessSettingListener l)83     public void registerListener(BrightnessSettingListener l) {
84         if (mListeners.contains(l)) {
85             Slog.wtf(TAG, "Duplicate Listener added");
86         }
87         mListeners.add(l);
88     }
89 
90     /**
91      * Unregisters listener for brightness setting change events.
92      *
93      * @param l listener
94      */
unregisterListener(BrightnessSettingListener l)95     public void unregisterListener(BrightnessSettingListener l) {
96         mListeners.remove(l);
97     }
98 
setBrightness(float brightness)99     void setBrightness(float brightness) {
100         if (Float.isNaN(brightness)) {
101             Slog.w(TAG, "Attempting to set invalid brightness");
102             return;
103         }
104         synchronized (mSyncRoot) {
105             // If the brightness is the same, we still need to update any listeners as the act of
106             // setting the brightness alone has side effects, like clearing any temporary
107             // brightness. We can skip persisting to disk, however, since it hasn't actually
108             // changed.
109             if (brightness != mBrightness) {
110                 mPersistentDataStore.setBrightness(mLogicalDisplay.getPrimaryDisplayDeviceLocked(),
111                         brightness);
112             }
113             mBrightness = brightness;
114             int toSend = Float.floatToIntBits(mBrightness);
115             Message msg = mHandler.obtainMessage(MSG_BRIGHTNESS_CHANGED, toSend, 0);
116             mHandler.sendMessage(msg);
117         }
118     }
119 
120     /**
121      * @return The brightness for the default display in nits. Used when the underlying display
122      * device has changed but we want to persist the nit value.
123      */
getBrightnessNitsForDefaultDisplay()124     float getBrightnessNitsForDefaultDisplay() {
125         return mPersistentDataStore.getBrightnessNitsForDefaultDisplay();
126     }
127 
128     /**
129      * Set brightness in nits for the default display. Used when we want to persist the nit value
130      * even if the underlying display device changes.
131      * @param nits The brightness value in nits
132      */
setBrightnessNitsForDefaultDisplay(float nits)133     void setBrightnessNitsForDefaultDisplay(float nits) {
134         mPersistentDataStore.setBrightnessNitsForDefaultDisplay(nits);
135     }
136 
notifyListeners(float brightness)137     private void notifyListeners(float brightness) {
138         for (BrightnessSettingListener l : mListeners) {
139             l.onBrightnessChanged(brightness);
140         }
141     }
142 
143     /**
144      * Listener for changes to system brightness.
145      */
146     public interface BrightnessSettingListener {
147 
148         /**
149          * Notify that the brightness has changed.
150          */
onBrightnessChanged(float brightness)151         void onBrightnessChanged(float brightness);
152     }
153 }
154