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 (brightness == mBrightness) {
106                 return;
107             }
108 
109             mBrightness = brightness;
110             mPersistentDataStore.setBrightness(mLogicalDisplay.getPrimaryDisplayDeviceLocked(),
111                     brightness);
112             int toSend = Float.floatToIntBits(mBrightness);
113             Message msg = mHandler.obtainMessage(MSG_BRIGHTNESS_CHANGED, toSend, 0);
114             mHandler.sendMessage(msg);
115         }
116     }
117 
notifyListeners(float brightness)118     private void notifyListeners(float brightness) {
119         for (BrightnessSettingListener l : mListeners) {
120             l.onBrightnessChanged(brightness);
121         }
122     }
123 
124     /**
125      * Listener for changes to system brightness.
126      */
127     public interface BrightnessSettingListener {
128 
129         /**
130          * Notify that the brightness has changed.
131          */
onBrightnessChanged(float brightness)132         void onBrightnessChanged(float brightness);
133     }
134 }
135